Chris The Avatar's picture

Frame Buffer Rendering Upside Down...

I am currently trying to render a set of textured quads to a frame buffer tied to a texture. Everything I am rendering to the frame buffer object is appearing upside down when the final texture is rendered to the screen. I have tried resetting the projection matrix and playing with the viewport but nothing seems to be working. (I realize the origin point in OGL is left, bottom but I imagine this is changable) Could someone provide some help or a snippet of code. Below is a condensed version of my code. (Note other objects are rendering to the screen just fine):

    GL.Ext.BindFramebuffer(FramebufferTarget.DrawFramebuffer, s.FboID);
    GL.BindTexture(TextureTarget.Texture2D, Surf.GlTextureID);
    PointF[] dstVertex = new PointF[4];
                PointF[] srcVertex = new PointF[4];
                RectangleF srcCoords = new RectangleF(
                    SourceRect.X / (float)Surf.Width,
                    SourceRect.Y / (float)Surf.Height,
                    SourceRect.Right / (float)Surf.Width,
                    SourceRect.Bottom / (float)Surf.Height);
 
                srcVertex[0] = new PointF(srcCoords.Left, srcCoords.Top);
                srcVertex[1] = new PointF(srcCoords.Width, srcCoords.Top);
                srcVertex[2] = new PointF(srcCoords.Width, srcCoords.Height);
                srcVertex[3] = new PointF(srcCoords.Left, srcCoords.Height);
 
        GL.Begin(BeginMode.Quads);
 
 
                for (int i = 0; i < 4; i++)
                {
                    GL.TexCoord2(srcVertex[i].X, srcVertex[i].Y);
                    GL.Vertex2(dstVertex[i].X, dstVertex[i].Y);
 
                }
                GL.End();
    GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);

This seems to be somewhat of a common problem on the web, but I have failed to find a coherant solution (though some things are over my head)...

Anyway I thank you in advance, my end goal is to buffer many smaller textures to a larger texture (IE Frame Buffer) to reduce render calls in an effort to improve performance on my project.


Comments

Comment viewing options

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

As you already wrote, the origin of OpenGL textures is in the bottom left corner, therefore you have to draw your quad accordingly. The bottom left vertex of the quad has to have the texture coordinates (0, 0), not (0, 1). You just have to flip the y value of the texture coordinates for drawing.

I don't know if there is a "convenient" way to switch to top-left origins in the framebuffer and I don't see any use for it. But maybe this helps, it let's you change the convention of origin in the fragment shader.

Chris The Avatar's picture

just seems illogical that i can draw to the screen with point 0,0 at the top left after adjusting the projection/view port but not to the frame buffer.

mOfl's picture

You can do that, too, of course, if you scale your projection matrix by (1, -1, 1). But why would you do that? The "origin" is just a convention telling you how the data is aligned in the memory. Instead of changing the proper way it's written to the memory you should change the way you read it from there.

Chris The Avatar's picture

Thanks mOfl,

Not when im rendering all 2d quads, top left is the common origin for 2d programming... (All base functions for my drawing assume that is the origin to have to go through and change them to render to a different target seems silly) I am not much of a 3d programmer so a lot of this is foreign to me, I understand what i need to do though, this just seems like a small problem in my way.

Anyway, I changed the projection to the same parameters I used for the screen but that does not seem to be helping... Here are the parameters I am using once the frame buffer is bound as the target (note the width, and height are equal to the texture target width/height):

GL.Viewport(0, 0, Width, Height);
Matrix4 ortho_projection = Matrix4.CreateOrthographicOffCenter(0, Width, Height, 0, -1, 1);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref ortho_projection);

Chris The Avatar's picture

For anyone else running into this issue, reversing the projection matrix as mentioned above didnt help. here is what I had to do after scouring many opengl forums and q/a posts... Flipping the Quads around also only fixed half of the issue (the mirroring, but the overall end texture was still rendered in the incorrectly on the xy coordinate plane) so I kept searching. You must reset the projection and viewport to the screens before unbinding the frame buffer or your image will be flipped (not sure why but it is what is). Here is how I broke it down to simplify the whole off screen texture rendering:

The other change I made was reversing the bottom and top on the projection matrix in the start frame buffer function below (see bolded)
(Note: surface just encapsulates and manages the ids for the FB and texture... )

public void StartFrameBuffer(Surface s)
{
GL.Ext.BindFramebuffer(FramebufferTarget.DrawFramebuffer, s.FboID);
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);
GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0); // disable rendering into the FBO
}

----

You can then call:
StartFrameBuffer();
Render things as if you were rendering them to screen, and they go to frame buffer()
EndFrameBuffer();