the Fiddler's picture

OpenTK and WPF interoperation

Project:The Open Toolkit library
Version:all versions
Component:Code
Category:support request
Priority:normal
Assigned:Unassigned
Status:closed
Description

Right now, it is possible to create an OpenTK.GLControl and host it in a WPF using a WindowsFormsHost.

The question is: can we create an OpenGL context directly on a WPF window and do away with the host control?

The attached solution creates a WPF solution, obtains its handle and creates a GraphicsContext. This works without errors, however OpenGL rendering results in artifacts. The msdn entry for the OnRender method, notes that:

msdn wrote:

The rendering instructions for this element are not used directly when this method is invoked, and are instead preserved for later asynchronous use by layout and drawing.

This explains why the rendering artifacts appear: OpenGL tries to render to the window directly and does not participate into WPF composition.

One *could* use offscreen OpenGL rendering, perform a readback and present the results into the WPF window, but this is inefficient. It would be nice to find a better solution or confirm that it cannot be done.

Any ideas?

AttachmentSize
OpenTKWPF.zip1.81 MB

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
viewon01's picture

#31

WPF support :

        // Summary:
        //     No pixel format is specified.
        DontCare = 0,
        //
        // Summary:
        //     The pixel format is undefined.
        Undefined = 0,
        //
        // Summary:
        //     The maximum value for this enumeration.
        Max = 15,
        //
        // Summary:
        //     The pixel data contains color-indexed values, which means the values are
        //     an index to colors in the system color table, as opposed to individual color
        //     values.
        Indexed = 65536,
        //
        // Summary:
        //     The pixel data contains GDI colors.
        Gdi = 131072,
        //
        // Summary:
        //     Specifies that the format is 16 bits per pixel; 5 bits each are used for
        //     the red, green, and blue components. The remaining bit is not used.
        Format16bppRgb555 = 135173,
        //
        // Summary:
        //     Specifies that the format is 16 bits per pixel; 5 bits are used for the red
        //     component, 6 bits are used for the green component, and 5 bits are used for
        //     the blue component.
        Format16bppRgb565 = 135174,
        //
        // Summary:
        //     Specifies that the format is 24 bits per pixel; 8 bits each are used for
        //     the red, green, and blue components.
        Format24bppRgb = 137224,
        //
        // Summary:
        //     Specifies that the format is 32 bits per pixel; 8 bits each are used for
        //     the red, green, and blue components. The remaining 8 bits are not used.
        Format32bppRgb = 139273,
        //
        // Summary:
        //     Specifies that the pixel format is 1 bit per pixel and that it uses indexed
        //     color. The color table therefore has two colors in it.
        Format1bppIndexed = 196865,
        //
        // Summary:
        //     Specifies that the format is 4 bits per pixel, indexed.
        Format4bppIndexed = 197634,
        //
        // Summary:
        //     Specifies that the format is 8 bits per pixel, indexed. The color table therefore
        //     has 256 colors in it.
        Format8bppIndexed = 198659,
        //
        // Summary:
        //     The pixel data contains alpha values that are not premultiplied.
        Alpha = 262144,
        //
        // Summary:
        //     The pixel format is 16 bits per pixel. The color information specifies 32,768
        //     shades of color, of which 5 bits are red, 5 bits are green, 5 bits are blue,
        //     and 1 bit is alpha.
        Format16bppArgb1555 = 397319,
        //
        // Summary:
        //     The pixel format contains premultiplied alpha values.
        PAlpha = 524288,
        //
        // Summary:
        //     Specifies that the format is 32 bits per pixel; 8 bits each are used for
        //     the alpha, red, green, and blue components. The red, green, and blue components
        //     are premultiplied, according to the alpha component.
        Format32bppPArgb = 925707,
        //
        // Summary:
        //     Reserved.
        Extended = 1048576,
        //
        // Summary:
        //     The pixel format is 16 bits per pixel. The color information specifies 65536
        //     shades of gray.
        Format16bppGrayScale = 1052676,
        //
        // Summary:
        //     Specifies that the format is 48 bits per pixel; 16 bits each are used for
        //     the red, green, and blue components.
        Format48bppRgb = 1060876,
        //
        // Summary:
        //     Specifies that the format is 64 bits per pixel; 16 bits each are used for
        //     the alpha, red, green, and blue components. The red, green, and blue components
        //     are premultiplied according to the alpha component.
        Format64bppPArgb = 1851406,
        //
        // Summary:
        //     The default pixel format of 32 bits per pixel. The format specifies 24-bit
        //     color depth and an 8-bit alpha channel.
        Canonical = 2097152,
        //
        // Summary:
        //     Specifies that the format is 32 bits per pixel; 8 bits each are used for
        //     the alpha, red, green, and blue components.
        Format32bppArgb = 2498570,
        //
        // Summary:
        //     Specifies that the format is 64 bits per pixel; 16 bits each are used for
        //     the alpha, red, green, and blue components.
        Format64bppArgb = 3424269,

But for glReadPixel, which format should I use ?

I can't find a match between theses 2 technologies !!!!

the Fiddler's picture

#32

Argb in WPF or GDI+ equals Bgra in OpenGL.

Try Format32bppRgb in WPF and Bgra in ReadPixels.

viewon01's picture

#33

Thanks,

It is strange that GL_BGRA correspond to PixelFormat.Format32bppRgb, where have you see this information ?
It sounds to be the inverse :-P ... even there is a Format32bppArgb more too !

Anyway, it change nothing ... maybe the problem is in the configuration of the RenderBuffer or the FrameBuffer :

Here is my code that play with colors modes :

Gl.glRenderbufferStorageEXT(Gl.GL_RENDERBUFFER_EXT, Gl.GL_RGBA8, width, height);
 
_bitmapData = _bitmap.LockBits(new System.Drawing.Rectangle(0, 0, _form.ClientSize.Width, _form.ClientSize.Height),
                                                System.Drawing.Imaging.ImageLockMode.ReadWrite,
                                                System.Drawing.Imaging.PixelFormat.Format32bppRgb);
 
Gl.glReadPixels(0, 0, _form.ClientSize.Width, _form.ClientSize.Height, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, _bitmapData.Scan0);
viewon01's picture

#34

Thanks,

It is strange that GL_BGRA correspond to PixelFormat.Format32bppRgb, where have you see this information ?
It sounds to be the inverse :-P ... even there is a Format32bppArgb more too !

Anyway, it change nothing ... maybe the problem is in the configuration of the RenderBuffer or the FrameBuffer :

Here is my code that play with colors modes :

Gl.glRenderbufferStorageEXT(Gl.GL_RENDERBUFFER_EXT, Gl.GL_RGBA8, width, height);
 
_bitmapData = _bitmap.LockBits(new System.Drawing.Rectangle(0, 0, _form.ClientSize.Width, _form.ClientSize.Height),
                                                System.Drawing.Imaging.ImageLockMode.ReadWrite,
                                                System.Drawing.Imaging.PixelFormat.Format32bppRgb);
 
Gl.glReadPixels(0, 0, _form.ClientSize.Width, _form.ClientSize.Height, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, _bitmapData.Scan0);
viewon01's picture

#35

Wow,

Finally I have solve every problems and the control sounds to working correctly now.

Thanks for all your help.

Regards

zahirtezcan's picture

#36

i am glad that you solve the problems. i met a function in the specs that i did not know of: "BlitFrameBuffer", which blits contents of readbuffer to drawbuffer. i did not try this but the spec suggests that if source height is negative than the image would be reversed. i missed the point where you solved the inverse image problem. so in case i wrote this message.

Polidobj's picture

#37

Is that working control available for use?

viewon01's picture

#38

Not really,

I have worked at lot to try to get a good control... I have got several versions of the control, based on differents approach but none work with acceptable performance.

The best is to use a WindowsFormsHost... if performance is important for you

the Fiddler's picture

#39

Version:0.9.9-2b» all versions
Status:in progress (review)» closed

Working WindowsFormsHost + OpenTK.GLControl example at https://github.com/thefiddler/opentk-wpf

Can be used with either desktop OpenGL or ANGLE (OpenGL ES over Direct3d!)

freakinpenguin's picture

#40

Hi Guys,
I've put some work in this and want to share my results.
I'm using the approach discussed in this thread, i.e. I have an Framebuffer in which I render my content and read it back via ReadPixels. The content is saved into a WriteableBitmap. By using this class OpenTK can write directly into a WPF-ImageSource.
I've uploaded my example project to github: https://github.com/freakinpenguin/OpenTK-WPF

Would be great if you can take a look at the project and give me some feedback.
Greetings