Original Post
Hello, I'm trying to write a program to simulate depth of field using Cg shaders and framebuffer objects. The program is supposed to render the scene to a framebuffer object, then blur each pixel in the color buffer based on the value of the corresponding pixel in the depth buffer. However, as far as I can tell, either the depth buffer contains the same data as the color buffer (which doesn't make any sense), or I am sending the wrong data to the Cg shader. What am I doing wrong? I'm running this on an Nvidia GeForce 6800, driver version 77.77. I got most of the framebuffer-related code from the EXT_framebuffer_object documentation examples. Any help would be appreciated. Framebuffer initialization: Rendering code (in a loop): Sorry for the huge amount of code. Note that config.screenX = 512 and config.screenY = 512
glGenFramebuffersEXT(1, &fb);
glGenTextures(1, &texid);
glGenRenderbuffersEXT(1, &depth_rb);
// initialize color texture
glBindTexture(GL_TEXTURE_2D, texid);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 512, 512, 0, GL_RGB, GL_INT, NULL);
// establish a mipmap chain for the texture
glGenerateMipmapEXT(GL_TEXTURE_2D);
// initialize depth renderbuffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, 512, 512);
// setup framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texid, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
// error checking
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
errorLog.Print("GL_FRAMEBUFFER_COMPLETE_EXT");
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
errorLog.OutputError("GL_FRAMEBUFFER_UNSUPPORTED_EXT ...exiting");
exit(0);
break;
default:
errorLog.OutputError("Unknown Framebuffer Error ...exiting");
exit(0);
}
// Disable lighting in RTT mode
glDisable(GL_LIGHTING);
// set up depth parameters
glClearDepth(1.0f);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glBindTexture(GL_TEXTURE_2D, 0);
// bind buffers and make attachments
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texid, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
//set up viewport, clear screen
glViewport( 0, 0, config.screenX, config.screenY );
glClearColor(0.96f, 0.96f, 0.86f, 1.0f); // beige
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear screen and depth buffer
persp_reshape();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
camera.setPerspective(); // position the camera
// copy modelview matrix to vertex shader parameter
modelViewMatrix = cgGetNamedParameter(cgv_program, "modelViewProj");
if (modelViewMatrix == NULL)
errorLog.OutputError("failed to bind matrix (NULL returned)");
cgGLSetStateMatrixParameter(modelViewMatrix, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
// passthrough fragment program for initial render-to-texture
cgGLLoadProgram(cgf_passthru);
cgGLEnableProfile(CG_PROFILE_FP30);//cgf_profile);
cgGLBindProgram(cgf_passthru);
tex_2d = cgGetNamedParameter(cgf_passthru, "tex");
// Draw objects
// each Thing binds/unbinds its own texture in render()
for (unsigned int i = 0; i < things.size(); ++i)
things.render(true);
// Draw floor
glColor4f(1.0, 1.0, 1.0, 1.0);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
cgGLSetTextureParameter(tex_2d, textures[0]);
cgGLEnableTextureParameter(tex_2d);
glBegin(GL_QUADS);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2i(0, 0);
glVertex3f(-100.0f, 0.0f, 100.0f);
glTexCoord2i(1, 0);
glVertex3f( 100.0f, 0.0f, 100.0f);
glTexCoord2i(1, 1);
glVertex3f( 100.0f, 0.0f, -200.0f);
glTexCoord2i(0, 1);
glVertex3f(-100.0f, 0.0f, -200.0f);
glEnd();
cgGLDisableTextureParameter(tex_2d);
glPopMatrix();
glFlush();
// disable Cg profile
cgGLDisableProfile(CG_PROFILE_FP30);
// unbind framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
//glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
// Reset the screen and camera
ortho_reshape();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Calculate uniform values (these don't change during shader execution)
// User-controlled values are aperture, focaldistance, and planeinfocus
// Calculate scale and bias (used to calculate CoC in fragment shader)
GLdouble CoCscale = (lens.aperture * lens.focallength * lens.planeinfocus * (camera.zFar - camera.zNear)) /
((lens.planeinfocus - lens.focallength) * camera.zNear * camera.zFar);
GLdouble CoCbias = (lens.aperture * lens.focallength * (camera.zNear - lens.planeinfocus)) /
((lens.planeinfocus * lens.focallength) * camera.zNear);
// Enable the shader and set parameters
cgGLLoadProgram(cgf_simpledof);
cgGLEnableProfile(CG_PROFILE_FP30);//cgf_profile);
cgGLBindProgram(cgf_simpledof);
tex_color = cgGetNamedParameter(cgf_simpledof, "colortex");
tex_depth = cgGetNamedParameter(cgf_simpledof, "depthtex");
dofbias = cgGetNamedParameter(cgf_simpledof, "bias");
dofscale = cgGetNamedParameter(cgf_simpledof, "scale");
cgGLSetParameter1d(dofbias, CoCbias);
cgGLSetParameter1d(dofscale, CoCscale);
cgGLSetTextureParameter(tex_color, texid);
cgGLSetTextureParameter(tex_depth, depth_rb);
cgGLEnableTextureParameter(tex_color);
cgGLEnableTextureParameter(tex_depth);
// Bind framebuffer as texture
glBindTexture(GL_TEXTURE_2D, texid);
glGenerateMipmapEXT(GL_TEXTURE_2D); // automatically generate mipmaps
// Render fullscreen quad w/ shader enabled
glBegin(GL_QUADS);
glTexCoord2f(0.f, 0.f);
glVertex2i(0, 0);
glTexCoord2f(1.f, 0.f);
glVertex2i(config.screenX, 0);
glTexCoord2f(1.f, 1.f);
glVertex2i(config.screenX, config.screenY);
glTexCoord2f(0.f, 1.f);
glVertex2i(0, config.screenY);
glEnd();
// Disable the shader because we're done
cgGLDisableTextureParameter(tex_depth);
cgGLDisableTextureParameter(tex_color);
cgGLDisableProfile(CG_PROFILE_FP30); // Disable fragment profile
cgGLDisableProfile(cgv_profile); // Disable vertex profile
glEnable(GL_DEPTH_TEST);
glFlush();