4
\$\begingroup\$

I am learning to use Frame Buffer Objects. For this purpose, I chose to render a triangle to a texture and then map that to a quad.

When I render the triangle, I clear the color to something blue. So, when I render the texture on the quad from fbo, it only renders everything blue, but doesn't show up the triangle. I can't seem to figure out why this is happening. Can someone please help me out with this ?

I'll post the rendering code here, since glCheckFramebufferStatus doesn't complain when I setup the FBO. I've pasted the setup code at the end. Here is my rendering code:

void FrameBufferObject::Render(unsigned int elapsedGameTime)
{
    glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);
    glClearColor(0.0, 0.6, 0.5, 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // adjust viewport and projection matrices to texture dimensions
    glPushAttrib(GL_VIEWPORT_BIT);
    glViewport(0,0, m_FBOWidth, m_FBOHeight);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, m_FBOWidth, 0, m_FBOHeight, 1.0, 100.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    DrawTriangle();

    glPopAttrib();
    // setting FrameBuffer back to window-specified Framebuffer
    glBindFramebuffer(GL_FRAMEBUFFER, 0);       //unbind

    // back to normal viewport and projection matrix
    //glViewport(0, 0, 1280, 768);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, 1.33, 1.0, 1000.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    render(elapsedGameTime);
}

void FrameBufferObject::DrawTriangle()
{
    glPushMatrix();

    glBegin(GL_TRIANGLES);
        glColor3f(1, 0, 0);

        glVertex2d(0, 0);
        glVertex2d(m_FBOWidth, 0);
        glVertex2d(m_FBOWidth, m_FBOHeight);

    glEnd();

    glPopMatrix();
}

void FrameBufferObject::render(unsigned int elapsedTime)
{
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, m_TextureID);

    glPushMatrix();

        glTranslated(0, 0, -20);

    glBegin(GL_QUADS);
        glColor4f(1, 1, 1, 1);

        glTexCoord2f(1, 1);  glVertex3f(1,1,1);
        glTexCoord2f(0, 1);  glVertex3f(-1,1,1);
        glTexCoord2f(0, 0);  glVertex3f(-1,-1,1);
        glTexCoord2f(1, 0);  glVertex3f(1,-1,1);

    glEnd();
    glPopMatrix();

    glBindTexture(GL_TEXTURE_2D, 0);
    glDisable(GL_TEXTURE_2D);

}

void FrameBufferObject::Initialize()
{
    // Generate FBO
    glGenFramebuffers(1, &m_FBO);
    glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);

    // Add depth buffer as a renderbuffer to fbo
    // create depth buffer id

    glGenRenderbuffers(1, &m_DepthBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer);

    // allocate space to render buffer for depth buffer
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_FBOWidth, m_FBOHeight);

    // attaching renderBuffer to FBO
    // attach depth buffer to FBO at depth_attachment
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_DepthBuffer);

    // Adding a texture to fbo
    // Create a texture
    glGenTextures(1, &m_TextureID);
    glBindTexture(GL_TEXTURE_2D, m_TextureID);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_FBOWidth, m_FBOHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // onlly allocating space
    glBindTexture(GL_TEXTURE_2D, 0);

    // attach texture to FBO
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_TextureID, 0);

    // Check FBO Status
    if( glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        std::cout << "\n Error:: FrameBufferObject::Initialize() :: FBO loading not complete \n";

    // switch back to window system Framebuffer
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

Thanks!

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

Everything was fine. The triangle I was rendering for the FBO was getting clipped which is why I was not seeing anything. A translate Z of -20 is all it took to get the triangle rendering properly.

A (obvious) thing I learnt: When the user FBO is not working properly, render it to the normal framebuffer and see if what you expect to show up in the user FBO, actually shows up there. If not, you have a problem in the way you are rendering to the user FBO.

Hope it helps someone.

\$\endgroup\$
1
  • \$\begingroup\$ Unfortunately, I have the same issue as you, but when I don't bind the framebuffer and draw the objects normally, I can indeed see the objects I'm drawing :(. Still, thanks for the suggestion, \$\endgroup\$
    – joehot200
    Nov 17, 2015 at 14:15
2
\$\begingroup\$

There doesn't seem to anything inherently wrong to your code. It might be in your initialization, but you haven't posted that.

That you have a blue rectangle on the screen means your FBO is working right, your problem is in the rendering of the triangle.

Try turning backface culling into frontface culling before rendering:

glCullFace(GL_FRONT);

Alternatively, just copy a triangle from a NeHe tutorial and see if that works.

glBegin(GL_TRIANGLES);                      // Drawing Using Triangles
    glVertex3f( 0.0f, 1.0f, 0.0f);              // Top
    glVertex3f(-1.0f,-1.0f, 0.0f);              // Bottom Left
    glVertex3f( 1.0f,-1.0f, 0.0f);              // Bottom Right
glEnd();                            // Finished Drawing The Triangle

EDIT: Second stab at solving this problem. Maybe the FBO isn't initialized properly?

My own version of the FBO init code:

RenderTarget::RenderTarget( unsigned int a_Width, unsigned int a_Height, int a_Colors/* = 1*/, bool a_Depth/* = true*/)
{
    m_Width = a_Width;
    m_Height = a_Height;
    m_Ratio = (float)m_Width / (float)m_Height;

    // this function returns the width and height if a system doesn't have
    // non-power of two texture support
    GetTextureSizes(&m_TexWidth, m_Width, &m_TexHeight, m_Height);

    m_TextureColors = a_Colors;
    m_TextureTotal = a_Colors;
    if (a_Depth) { m_TextureTotal++; }

    m_Texture = new GLuint[m_TextureTotal];
    glGenTextures(m_TextureTotal, m_Texture);
    m_TexDepth = NULL;

    glGenFramebuffersEXT(1, &m_Target);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_Target);

    glEnable(GL_TEXTURE_2D);

    int i = 0;
    for (; i < a_Colors; i++)
    {
        glBindTexture(GL_TEXTURE_2D, m_Texture[i]);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_TexWidth, m_TexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, m_Texture[i], 0);
    }
    if (a_Depth)
    {
        m_TexDepth = m_Texture[i];

        glBindTexture(GL_TEXTURE_2D, m_TexDepth);

        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, m_TexWidth, m_TexHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);

        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, m_TexDepth, 0);
    }
    glBindTexture(GL_TEXTURE_2D, 0);
    glDisable(GL_TEXTURE_2D);

    GLenum status;

    status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
    {
        int i = 0;
    }
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

As you can see, I attach a depth texture, not a depth render target.

\$\endgroup\$
4
  • \$\begingroup\$ I just updated the last segment of the post with initialization code. Also, I render them in a counter-clockwise order, so it shouldn't be the problem. I'll try to see if that helps though. \$\endgroup\$ Feb 19, 2011 at 9:28
  • \$\begingroup\$ That didn't help. Also, as a test, I simply rendered the triangle without FBO and it was rendering correctly. \$\endgroup\$ Feb 19, 2011 at 9:31
  • \$\begingroup\$ Then I suspect your depth buffer is not attached properly. I will post my own version of the init. \$\endgroup\$
    – knight666
    Feb 19, 2011 at 9:48
  • \$\begingroup\$ Thanks for posting the code. I'll try and see if depth texture works. Also, what do you think of setting the viewport/projection matrices in the Render() initially ? Does that look ok ? \$\endgroup\$ Feb 19, 2011 at 17:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .