Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: FBO render to texture using VBO

  1. #1
    Junior Member Newbie
    Join Date
    Nov 2012
    Posts
    7

    FBO render to texture using VBO

    I'm using OpenTK and am trying to render to an FBO texture as per the tutorial here:

    http://www.opentk.com/node/397
    http://www.opentk.com/files/Program_0.cs

    This example uses immediate mode to draw triangles to the texture but I'd like to use VBO. I'm very new to OpenGL and have my rendering working using VBO but I don't know how to replace the random triangle rendering in this tutorial with DrawElements using VBO.

    Does anyone know of a tutorial which uses VBO to render to a FBO?

  2. #2
    Junior Member Newbie
    Join Date
    Nov 2012
    Posts
    7
    Alternatively my code is below if someone is able to see the problem.

    My working VBO render (renders my world as expected):

    Code :
    protected override void OnRenderFrame_VBO(FrameEventArgs e)
    {
        base.OnRenderFrame(e);
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
     
        // Camera.
        Matrix4 lookat = Matrix4.LookAt(this.Camera, this.Target, this.LocalUp);
        GL.MatrixMode(MatrixMode.Modelview);
        GL.LoadMatrix(ref lookat);
        GL.Viewport(0, 0, this.Width, this.Height);
        double aspect_ratio = this.Width / (double)this.Height;
        OpenTK.Matrix4 perspective = OpenTK.Matrix4.CreatePerspectiveFieldOfView(fov, (float)aspect_ratio, 1, 25000);
        GL.MatrixMode(MatrixMode.Projection);
        GL.LoadMatrix(ref perspective);
     
        // Colour Array.
        GL.BindBuffer(BufferTarget.ArrayBuffer, buffers.ColoursBufferId);
        GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(int), IntPtr.Zero);
        GL.EnableClientState(ArrayCap.ColorArray);
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
     
        // Vertex Data Array.
        GL.BindBuffer(BufferTarget.ArrayBuffer, buffers.VertexDataArrayBufferId);
        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(world.Vertices.Length * Vector3.SizeInBytes), world.Vertices, BufferUsageHint.StreamDraw);
        GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, IntPtr.Zero);
        GL.EnableClientState(ArrayCap.VertexArray);
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
     
        // Index Array.
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, buffers.ElementIndicesBufferId);
     
        GL.DrawElements(BeginMode.Triangles, world.Indices.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);
        this.SwapBuffers();
    }

    And my FBO code which is not working (renders all red):

    Code :
    public static void OnLoad(EventArgs e)
    {
     
        <<Working VBO creation logic here>>
     
        // Create Color Tex
        GL.GenTextures(1, out buffers.ColourTexture);
        GL.BindTexture(TextureTarget.Texture2D, buffers.ColourTexture);
        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, this.OffscreenFBOWidth, this.OffscreenFBOHeight, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToBorder);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToBorder);
        // GL.Ext.GenerateMipmap( GenerateMipmapTarget.Texture2D );
     
        // Create a FBO and attach the textures
        GL.Ext.GenFramebuffers(1, out buffers.FBOHandle);
        GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, buffers.FBOHandle);            
        GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0Ext, TextureTarget.Texture2D, buffers.ColourTexture, 0);
     
        if (GL.Ext.CheckFramebufferStatus(FramebufferTarget.FramebufferExt) != FramebufferErrorCode.FramebufferCompleteExt)
        {
            throw new Exception(GL.Ext.CheckFramebufferStatus(FramebufferTarget.FramebufferExt).ToString());
        }
     
        GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
        GL.BindTexture(TextureTarget.Texture2D, 0);
    }
     
    protected override void OnRenderFrame(FrameEventArgs e)
    {
        base.OnRenderFrame(e);
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
     
        // Camera.
        Matrix4 lookat = Matrix4.LookAt(this.Camera, this.Target, this.LocalUp);
        GL.MatrixMode(MatrixMode.Modelview);
        GL.LoadMatrix(ref lookat);
        GL.Viewport(0, 0, this.OffscreenFBOWidth, this.OffscreenFBOHeight);
        double aspect_ratio = Width / (double)Height;
        OpenTK.Matrix4 perspective = OpenTK.Matrix4.CreatePerspectiveFieldOfView(fov, (float)aspect_ratio, 1, 25000);
        GL.MatrixMode(MatrixMode.Projection);
        GL.LoadMatrix(ref perspective);
     
        // Bind FBO.
        GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, buffers.FBOHandle);
     
        GL.ClearColor(0f, 0f, .7f, 0f);
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
     
        // Render VBO.
        // Colour Array. 
        GL.BindBuffer(BufferTarget.ArrayBuffer, buffers.ColoursBufferId);
        GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(int), IntPtr.Zero);
        GL.EnableClientState(ArrayCap.ColorArray);
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
     
        // Vertex Data Array.
        GL.BindBuffer(BufferTarget.ArrayBuffer, buffers.VertexDataArrayBufferId);
        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(world.Vertices.Length * Vector3.SizeInBytes), world.Vertices, BufferUsageHint.StreamDraw);
        GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, IntPtr.Zero);
        GL.EnableClientState(ArrayCap.VertexArray);
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
     
        // Index Array.
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, buffers.ElementIndicesBufferId);
        GL.DrawElements(BeginMode.Triangles, world.Indices.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);   
     
        GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);            
     
        GL.ClearColor(.4f, 0f, 0f, 0f);
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);            
        GL.Enable(EnableCap.Texture2D);
     
        GL.BindTexture(TextureTarget.Texture2D, 0);           
     
        GL.PushMatrix();
        {
            GL.Translate(-1.1f, 0f, 0f);
            GL.BindTexture(TextureTarget.Texture2D, buffers.ColourTexture);            
     
            GL.Begin(BeginMode.Quads);
            {
                GL.TexCoord2(0f, 1f);
                GL.Vertex2(-1.0f, 1.0f);
                GL.TexCoord2(0.0f, 0.0f);
                GL.Vertex2(-1.0f, -1.0f);
                GL.TexCoord2(1.0f, 0.0f);
                GL.Vertex2(1.0f, -1.0f);
                GL.TexCoord2(1.0f, 1.0f);
                GL.Vertex2(1.0f, 1.0f);
            }
            GL.End();                
        }
        GL.PopMatrix();            
     
        this.SwapBuffers();
    }

    I'll take any pointers...

  3. #3
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,117
    I think your quad points are mixed up

    try
    Code :
      GL.TextCoord2(0.0f,0.0f);
      GL.Vertex2(-1.0f,-1.0f);
      GL.TextCoord2(1.0f,0.0f);
      GL.Vertex2(1.0f,-1.0f);
      GL.TextCoord2(1.0f,1.0f);
      GL.Vertex2(1.0f,1.0f);
      GL.TextCoord2(0.0f,1.0f);
      GL.Vertex2(-1.0f,1.0f);

  4. #4
    Junior Member Newbie
    Join Date
    Nov 2012
    Posts
    7
    Just tried your code but still no joy.

    Thanks for the suggestion I really appreciate it.

  5. #5
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,117
    If you don't bind a texture for the quad draw but just set a colour does the quad draw in the colour?
    eg render a blue quad over the background.

    Code :
     
    GL.Begin(BeginMode.Quads);
      GL.Color3f(0.0f,1.0f,0.0f); 
      GL.Vertex2(-1.0f, 1.0f);
      GL.Vertex2(-1.0f, -1.0f);
      GL.Vertex2(1.0f, -1.0f);
      GL.Vertex2(1.0f, 1.0f); 
    GL.End();

    This will at least remove the quad draw as a problem

  6. #6
    Junior Member Newbie
    Join Date
    Nov 2012
    Posts
    7
    Good idea.

    Code :
    GL.PushMatrix();
    {
        GL.BindTexture(TextureTarget.Texture2D, 0);           
        GL.Begin(BeginMode.Quads);
        {
            GL.Color3(0f, .6f, 0f);
            GL.Vertex2(-1.0f, -1.0f);
            GL.Vertex2(1.0f, -1.0f);
            GL.Vertex2(1.0f, 1.0f);
            GL.Vertex2(-1.0f, 1.0f);
        }
        GL.End();
     
        GL.Begin(BeginMode.Quads);
        {
            GL.Color3(0f, 0f, .6f);
            GL.Vertex2(-1.0f, 1.0f);
            GL.Vertex2(-1.0f, -1.0f);
            GL.Vertex2(1.0f, -1.0f);
            GL.Vertex2(1.0f, 1.0f);
        }
        GL.End();           
    }
    GL.PopMatrix();

    I've tried the above (drawing the quad as you suggested and how it was originally) but I don't see either quad.

    That's great though. Now I know it's not a FBO issue. Thanks.

    I guess I need to reset the view after my VBO rendering. I thought this was achieved with GL.LoadIdentity() but adding GL.LoadIdentity() makes no difference.

  7. #7
    Junior Member Newbie
    Join Date
    Nov 2012
    Posts
    7
    Ok, finally got the quad rendering on screen.

    Once the VBO has been drawn to the FBO I'm calling GL.LoadIdentity() before and after applying a Modelview Matrix.

    Code :
    // Draw VBO to FBO.
    GL.DrawElements(BeginMode.Triangles, world.Indices.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);
    // Stop rendering to FBO.
    GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
     
    // Reset Matrix.
    GL.LoadIdentity();
    GL.MatrixMode(MatrixMode.Modelview);
    GL.LoadIdentity();
     
    // Draw FBO as texture.
    GL.ClearColor(0f, Convert.ToSingle(this.rand.NextDouble()), 1f, 0f);    // Greenish.
    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
     
    GL.PushMatrix();
    {
        GL.BindTexture(TextureTarget.Texture2D, Rendering.Controller.buffers.ColourTexture);
        GL.Begin(BeginMode.Quads);
        {
            GL.TexCoord2(0.0f, 0.0f);
            GL.Vertex2(-1.0f, -1.0f);
            GL.TexCoord2(1.0f, 0.0f);
            GL.Vertex2(1.0f, -1.0f);
            GL.TexCoord2(1.0f, 1.0f);
            GL.Vertex2(1.0f, 1.0f);
            GL.TexCoord2(0.0f, 1.0f);
            GL.Vertex2(-1f, 1.0f);
        }
        GL.End();
    }
    GL.PopMatrix();

    The FBO isn't rendering full-screen and the colours are all a shade of green, but I think that's progress.

  8. #8
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,117
    Yes that sounds like progress.

    The GL.LoadIdentity should not be done prior to the GL.MatrixMode(MatrixMode.Modelview) as it changes the matix of the last

    GL.MatrixMode before it, which is not what you want.

    The next step in debugging is to use the code that renders to the texture buffer to just render straight to the screen
    so you can see what is being rendered to the texture.

    (The alernate is to save the texture to a file as an image that you can look at but that might actually be more work
    than is necessary).

  9. #9
    Junior Member Newbie
    Join Date
    Nov 2012
    Posts
    7
    If I remove the GL.LoadIdentity() prior to the GL.MatrixMode(MatrixMode.Modelview) then nothing is rendered. I guess this means I probably have some bigger issue?

    This is how my rendering looks without using FBO (clear colour is pink):


    This is the same frame with my FBO code (FBO clear red, quad rendering clear blue):


    The image in the bottom left is the FBO but it should be full screen and with the colours as per the non FBO render.

    I'm fairly happy now that the FBO rendering is working because the first call to render draws the FBO with the right colours, just not full screen.

  10. #10
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,117
    It looks like you FBO render is only rendering the red channel but I don't know why. You can confirm this by clearing the backgroundto with say white and
    see what clear colour appears when you render the FBO texture.

    Just some other notes

    Usually your

    GL.PushMatrix(); GL.PopMatrix();
    are around any changes to the matrices not after you change them. The idea is to also know what state the matrices are in.

    Check you calls to glViewport since this effect where things are drawn on the window. Also check calls GL.MatrixMode to see what matrix is being set to identity matrix - I assume it is the projection matrix since
    I think it need to be set to identity as well to render a whole screenquad (I am a bit vague because I have been using shaders to do this for so long I forget exactly how the old fixed pipeline works).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •