2
\$\begingroup\$

I'm having trouble implementing render to texture with OpenGL 3.

My issue is that after rendering to the frame buffer, it appears the rendered object becomes deformed, which may imply a bad transformation has occurred somewhere. Which doesn't make sense as the object renders fine when not using my frame buffer (see bottom of post).

The current result is such:

Current result http://k.minus.com/jZVgUuLYRtapv.jpg

And the expected result was this (or something similar, this has just been GIMP'd): Expected http://k.minus.com/jA5rLM8lmXQYL.jpg

It therefore implies that I'm doing something wrong in my frame buffer set up code, or elsewhere. But I can't see what.


The FBO is set up through the following function:

unsigned int fbo_id;
unsigned int depth_buffer;
int m_FBOWidth, m_FBOHeight;
unsigned int m_TextureID;

void initFBO() {
    m_FBOWidth = screen_width;
    m_FBOHeight = screen_height;

    glGenRenderbuffers(1, &depth_buffer);
    glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_FBOWidth, m_FBOHeight);

    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);
    glBindTexture(GL_TEXTURE_2D, 0);

    glGenFramebuffers(1, &fbo_id);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_buffer);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_TextureID, 0);

    assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

Here is my drawing box code, which just takes a transformation matrix and calls the appropriate functions. The current values of P is a projection matrix, and an identity matrix for the view matrix (V).

void drawBox(const Matrix4& M) {
    const Matrix4 MVP = M * V * P;

    if (boundshader) {
        glUniformMatrix4fv((*boundshader)("MVP"), 1, GL_FALSE, &MVP[0]);
    }

    glBindVertexArray(vaoID);
    glDrawElements(GL_TRIANGLES, sizeof(cube.polygon)/sizeof(cube.polygon[0]), GL_UNSIGNED_INT, 0);
}

void drawStaticBox() {
    Matrix4 M(1);
    translate(M, Vector3(0,0,-50));

    drawBox(M);
}

void drawRotatingBox() {
    Matrix4 M(1);
    rotate(M, rotation(Vector3(1, 0, 0), rotation_x));
    rotate(M, rotation(Vector3(0, 1, 0), rotation_y));
    rotate(M, rotation(Vector3(0, 0, 1), rotation_z));
    translate(M, Vector3(0,0,-50));

    drawBox(M);
}

And the display function called by GLUT.

void OnRender() {
    /////////////////////////////////////////
    // Render to FBO

    glClearColor(0, 0, 0.2f,0);

    glBindFramebuffer(GL_FRAMEBUFFER, fbo_id);
    glViewport(0, 0, m_FBOWidth, m_FBOHeight);
    glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
    GL_CHECK_ERRORS

    colorshader.Use();
    boundshader = &colorshader;

    drawRotatingBox();

    colorshader.UnUse();

    /////////////////////////////////////////
    // Render to Window

    glClearColor(0, 0, 0, 0);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glViewport(0, 0, screen_width, screen_height);
    glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
    GL_CHECK_ERRORS

    texshader.Use();
    boundshader = &texshader;

    glBindTexture(GL_TEXTURE_2D, m_TextureID);
    drawStaticBox();

    texshader.UnUse();

    // Swap le buffers
    glutSwapBuffers();
}

And... the obligatory texture shader code

vertex

#version 330

in vec2 vUV;
in vec3 vVertex;
smooth out vec2 vTexCoord;

uniform mat4 MVP;
void main()
{
   vTexCoord = vUV;
   gl_Position = MVP*vec4(vVertex,1);
}

fragment

#version 330
smooth in vec2 vTexCoord;
out vec4 vFragColor;

uniform sampler2D textureMap;

void main(void)
{
   vFragColor = texture(textureMap, vTexCoord);
}

The following is what is rendered when not using the FBO logic: What is rendered to the FBO http://k.minus.com/jiP7kTOSLLvHk.jpg


... Help?

Any ideas on what I may be doing wrong? Further source available on request.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Offhand looks like your UV coordinates are messed up. Try rendering the textured cube with just a static test image? \$\endgroup\$ Sep 22, 2011 at 6:56
  • \$\begingroup\$ I did test it on a test image, but I think you may be right. Ill check it out. \$\endgroup\$ Sep 22, 2011 at 22:27
  • \$\begingroup\$ @Jari... might want to make that an answer. Its been a long week. lol. \$\endgroup\$ Sep 24, 2011 at 6:31

2 Answers 2

1
\$\begingroup\$

Offhand looks like your UV coordinates are messed up. Try rendering the textured cube with just a static test image?

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the help mate, painless answer If there ever was one :) \$\endgroup\$ Sep 24, 2011 at 21:52
0
\$\begingroup\$

It looks as if part of the cube is getting near-clipped in the FBO version, which leads me to suspect something wrong with the projection matrix and/or viewport. Double-check those, maybe try explicitly setting glDepthRange(0, 1)?

\$\endgroup\$

You must log in to answer this question.

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