Chris The Avatar's picture

Issue with Framebuffer on some machines

Thank you for taking the time to field my question in advance. Currently I am using framebuffers to draw a 2d scene to and then saving that frame buffer. Overall its working great on about 95% of my users' machines however on older machines/video cards nothing seems to be rendering to the framebuffer or from the framebuffer when I draw to/from them.

I am not sure if I need to add/change what I am doing with the versions. I could really use some advice in this area? Below is my start and end frame buffer code:

(Also my underlying surfaces are 512x512 and 1024x1024)

public void StartFrameBuffer(Surface s, bool Clear)
        {
            if (GameInstance.GlobalScreen.DisplayDriverMajorVersion >= 3)
                GL.BindFramebuffer(FramebufferTarget.Framebuffer, s.FboID);
            else
                GL.Ext.BindFramebuffer(FramebufferTarget.Framebuffer, s.FboID);
            if (Clear)
            {
                GL.ClearColor(0, 0, 0, 255);
                GL.Clear(ClearBufferMask.ColorBufferBit);
            }
            Matrix4 ortho_projection = Matrix4.CreateOrthographicOffCenter(0, s.Width, 0, s.Height, -1, 1);
            GL.Viewport(0, 0, s.Width, s.Height);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadMatrix(ref ortho_projection);
        }
 
        public void EndFrameBuffer()
        {
            Matrix4 ortho_projection = Matrix4.CreateOrthographicOffCenter(0, GameInstance.GlobalScreen.Width, GameInstance.GlobalScreen.Height, 0, -1, 1);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadMatrix(ref ortho_projection);
            GL.Viewport(0, 0, GameInstance.GlobalScreen.Width, GameInstance.GlobalScreen.Height);
            if (GameInstance.GlobalScreen.DisplayDriverMajorVersion >= 3)
                GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
            else
                GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0); // disable rendering into the FBO
 
            ResetClearColor();
        }

Any ideas/changes would be helpful.

Thanks

Chris The Avatar


Comments

Comment viewing options

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

A few ideas:

  • Check that GL_EXT_framebuffer_object is supported before trying to use GL.Ext.BindFramebuffer:
    string[] extensions = GL.GetString(StringName.Extensions).Split(' ');
    // Check that GL_EXT_framebuffer_object exists in extensions
  • Check that GL_EXT_framebuffer_blit is supported before trying to use GL.Ext.BlitFramebuffer, in case you are using that. It's a different extension that's not as well supported on old GPUs.
  • Make sure the FBO is complete before trying to use it: https://github.com/opentk/opentk/blob/develop/Source/Examples/OpenGL/1.x...
  • Use GL.GetErrors() to make sure you are not running into some other error condition.
Chris The Avatar's picture

Thank you for the quick response and example,

Lets assume the extension is not supported on these cards... Then is there another call that should be used in its place? I Really need to implement some kind of off screen buffering.... Would this then have to be done completely via software or is there an alternative call for this for older video cards? It just seems like such a basic function, it is surprising this hasn't been supported for over a decade.

While the example is helpful in identifying the different cases; it is not beneficial in learning what to do if a certain case is hit... I guess it would be nice to have some idea of how to handle the different cases of when the FBO is not ready.

the Fiddler's picture

Unfortunately, hardware without FBO support still exists (the first Atom processors, for instance.) The only way to get off-screen rendering without FBO is to use the WGL_ARB_pbuffer extension. There are two caveats:

  • OpenTK does not support pbuffers out of the box. Indeed, SDL, GLFW and GLUT don't support them either.
  • It is not certain that hardware without FBO will support pbuffers.

Adding support is not hard - you'd need a new flag GraphicsContextFlags.PBuffer and to pass WGL_DRAW_TO_PBUFFER_ARB (or the GLX equivalent) in WinGLContext/X11GLContext. The process is described here: https://developer.nvidia.com/sites/default/files/akamai/gamedev/docs/Pix...

There are no plans to implement pbuffers in OpenTK, but I will accept a pull request that implements them.

How you react to a non-complete FBO attachment is extremely application-specific. The linked sample provides general recommendations ("attachments should have the same size"; "attachments should have the same format"; etc), but you should probably refer to the OpenGL Specification to understand the conditions under which each error may arise.

You can find a copy of the specification under opentk/Documentation/.