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

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

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks for the help mate, painless answer If there ever was one :) \$\endgroup\$ – deceleratedcaviar Sep 24 '11 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)?

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.