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.
As was pointed out by Jari Komppa on GameDev.stackexchange, and neodelphi as a comment on my main post.
The texture coordinates were wrong (or in my case, not passed).