Rendering offscreen

Nov 7, 2015 at 7:46 PM
How would you advise rendering into an offscreen buffer using SharpGL?

I've been looking at the RenderContextsSample project and the four enumerated SharpGL.RenderContextType's. It seems like using an FBO gets us most of the way way there. My C# WinForm programming is a bit rusty so I might be making some incorrect assumptions here but it seems like if we are using a FBORenderContextProvider it will present the results to the window that the OpenGLControl belongs to. What I would like to do is render to an image and then read it out to apply it as a texture later on.

I'm toying with the idea of making a new version of FBORenderContextProvider and adding a new SharpGL.RenderContextType enumeration to cover offscreen rendering where I basically do what FBORenderContextProvider does just with out doing the:
Win32.BitBlt(hdc, 0, 0, Width, Height, dibSectionDeviceContext, 0, 0, Win32.SRCCOPY); at the end of the Blit call.

Does this strategy make sense or will I run into problems trying to set an OpenGLControl that is hidden and not visible?
Jan 23 at 12:41 PM
To being with.. an FBO is known as a Frame Buffer Object, so you are already rendering offscreen.

The sameple ... FormRenderContextsSample example is using more then one OpenGL control, but using only one SampleRendering Method. You could make more of those methods and have one for each control you want to draw too. You would literally be drawing each one to its own FBO in this case.

However.. with all of this said.. you are doing this all using the CPU... not your graphics card. So its slower and more resource intensive.

What you want to look at is the Shader example.. its the only shader example they provide in the examples they have. Look for "ModernOpenGLSample" and you'll see how they work with the shaders to draw all of the vertices to the screen.

It does use double buffering though. Which in turn is what should be enabled to make it look smooth and draw better onto the screen.


Hopefully this info puts you in the right direction. Modern OpenGL uses shaders now.... The example you mentioned is the old way of using OpenGL. OpenGL 3.0+ is what you need. The provided example defaults to OpenGL 4.4. You can lower that down to 3.0 if you need too and it will work just fine. Just make sure your shader FRAG and VERT file versions are setup accordingly.
Jan 23 at 2:22 PM
This little piece of code should be able to help you create an empty texture.... or... Buffer Object in this case.

I added the Width and Height. This code is from the RadialBlur example.
    protected uint EmptyTexture(int Wdith, int Height)
    {
        uint[] txtnumber = new uint[1];                     // Texture ID

        byte[] data = new byte[((Wdith * Height)* 4 * sizeof(uint))];

        //  Get a reference to opengl to make things easier.
        OpenGL gl = openGLControl1.OpenGL;

     gl.GenTextures(1, txtnumber);                  // Create 1 Texture
        gl.BindTexture(OpenGL.GL_TEXTURE_2D, txtnumber[0]);         // Bind The Texture
        gl.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, 4, Wdith, Height, 0, OpenGL.GL_RGBA, OpenGL.GL_UNSIGNED_BYTE, data);         // Build Texture Using Information In data
        gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, OpenGL.GL_LINEAR);
        gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, OpenGL.GL_LINEAR);

        return txtnumber[0];                        // Return The Texture ID
    }