Since the problem is fixed (even if I don't understand which state was putting everything off), here is the full code of my FBO class and render function, in case someone runs into the same kind of problem:
/*
* FBO.cpp
*
* Created on: 28 Mar 2013
* Author: arnaud
*/
// Include GLEW
#include <GL/glew.h>
#include "FBO.h"
#include <GL/glext.h>
#include <iostream>
#include "FBOException.h"
using namespace std;
FBO::FBO(int width, int height) {
mWidth = width;
mHeight = height;
// TODO Auto-generated constructor stubc
init();
}
FBO::~FBO() {
// TODO Auto-generated destructor stub
glDeleteFramebuffersEXT(1, &mFrameBuffer);
}
void FBO::init() {
initDepthTexture();
initFBO();
}
void FBO::initDepthTexture() {
//32 bit depth texture, mWidth*mHeight
glGenTextures(1, &mDepthTex);
glBindTexture(GL_TEXTURE_2D, mDepthTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
//NULL means reserve texture memory, but texels are undefined
//You can also try GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24 for the internal format.
//If GL_DEPTH24_STENCIL8_EXT, go ahead and use it (GL_EXT_packed_depth_stencil)
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, mWidth, mHeight, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
}
void FBO::initFBO() {
glGenFramebuffersEXT(1, &mFrameBuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFrameBuffer);
//Attach
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_TEXTURE_2D, mDepthTex, 0);
//-------------------------
//Does the GPU support current FBO configuration?
//Before checking the configuration, you should call these 2 according to the spec.
//At the very least, you need to call glDrawBuffer(GL_NONE)
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
checkFBO();
renderToScreen();
}
void FBO::checkFBO() throw () {
GLenum status;
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
switch (status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
cout << "Good Framebuffer" << endl;
break;
case GL_FRAMEBUFFER_UNDEFINED:
throw new FBOException(
"Framebuffer undefined. Usually returned if returned if target is the default framebuffer, but the default framebuffer does not exist.");
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
throw new FBOException(
"Incomplete Attachement: is returned if any of the framebuffer attachment points are framebuffer incomplete.");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
throw new FBOException(
"Incomplete Missing Attachment: is returned if the framebuffer does not have at least one image attached to it.");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
throw new FBOException(
"Incomplete Draw Buffer: is returned if the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE for any color attachment point(s) named by GL_DRAWBUFFERi");
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
throw new FBOException(
"Incomplete Read Buffer: is returned if GL_READ_BUFFER is not GL_NONE and the value of\\"
" GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE for the color attachment point named by GL_READ_BUFFER");
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
throw new FBOException(
"Framebuffer Unsupported: is returned if the combination of internal formats of the attached images violates an implementation-dependent set of restrictions.");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
throw new FBOException("Incomplete Multisample");
break;
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
throw new FBOException("Incomplete Layer Targets");
break;
default:
throw new FBOException("Bad Framebuffer");
}
}
/****
* PUBLIC Functions
*/
void FBO::renderToFBO() {
cout << "Render to FBO: " << mFrameBuffer << endl;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFrameBuffer); // Bind our frame buffer for rendering
//-------------------------
//----and to render to it, don't forget to call
//At the very least, you need to call glDrawBuffer(GL_NONE)
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
}
/**
* Static
*/
void FBO::renderToScreen() {
cout << "Render to screen " << endl;
// Finish all operations
//glFlush();
//-------------------------
//If you want to render to the back buffer again, you must bind 0 AND THEN CALL glDrawBuffer(GL_BACK)
//else GL_INVALID_OPERATION will be raised
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
}
And here is the render function
void Viewer::onRender() {
// Get elapsed time since last loop
sf::Time time = mClock.getElapsedTime();
float ellapsedTime = time.asMilliseconds();
if (time.asMilliseconds() > 1000 / 60) {
// XXX: Need of Z-Depth sorting to get alpha blending right!!
glEnable(GL_DEPTH_TEST);
glClearColor(0., 0., 0.2, 1.);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glClearDepth(1.);
glDepthFunc(GL_LESS);
// set the projection transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLdouble) m_width / (GLdouble) m_height,
m_scale * 5.0, m_scale * 10000.0);
// set the model transformation
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glm::vec3 pos = mCamera->getPosition();
glm::vec3 view = mCamera->getView();
glm::vec3 up = mCamera->getUp();
gluLookAt(pos.x, pos.y, pos.z, view.x, view.y, view.z, up.x, up.y,
up.z);
static float rotationAngle = 0;
rotationAngle+=5;
/**
* Render geometry twice to FBOs
*/
mFBO->renderToFBO();
glClear(GL_DEPTH_BUFFER_BIT);
glClearDepth(0.);
glDepthFunc(GL_LESS);
glPushMatrix();
glColor3f(0., 1., 0.);
// Draw teapot
glutSolidTeapot(3.5);
glPopMatrix();
mFBO2->renderToFBO();
glClear(GL_DEPTH_BUFFER_BIT);
glClearDepth(0.);
glDepthFunc(GL_GREATER);
glPushMatrix();
glColor3f(0., 1., 0.);
// Draw teapot
glutSolidTeapot(3.5);
glPopMatrix();
/**
* Render the same geometry to the screen
*/
FBO::renderToScreen();
// XXX: Save attribs bits to fix FBO problem... (why is this needed!?)
glPushAttrib(GL_ALL_ATTRIB_BITS);
mShader->enable();
mShader->setTextureFromId("frontDepth", mFBO->getDepthTextureId());
mShader->setTextureFromId("backDepth", mFBO2->getDepthTextureId());
glBegin(GL_QUADS); // Draw A Quad
glTexCoord2f(0, 1);
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glTexCoord2f(1, 1);
glVertex3f(1.0f, 1.0f, 0.0f); // Top Right
glTexCoord2f(1, 0);
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glTexCoord2f(0, 0);
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glEnd(); // Done Drawing The Quad
mShader->disable();
glPopAttrib();
}
}