Hey All,
Sorry if this subject has been covered a lot, I’ve done searches for a few days now and have looked at many examples (even ones with source code) and I still haven’t been able to figure out why I can’t get this texture to display anything.
So, first some back story. I’m just trying to write a simple shadow mapping demo using no fixed function pipeline calls. I’ve been using the “OpenGL SuperBible 5” as my guide. So far, I’ve understood everything and I understand conceptually shadow mapping, I’m just having a heck of a time implementing it.
My scene is simple, there is a torus and a “floor” and the light will be rotating about the torus, but that’s not really my problem. The problem that I’m running into is that, after my first render pass (where I want to bind to the FBO and render the depth of the scene to a texture) I take the texture that is supposed to contain the depth information of the scene and render it to a quad. Unfortunately the screen is just black.
Again, I’m just trying to render the texture that is supposed to be the “depth texture” of the scene and nothing appears; the screen is all black. If I use a completely different texture (like one read in from a jpeg/tga/what have you) the quad shows that texture.
So, from that I’ve deduced that either, depth information is not being written to my “depth texture” or somehow my shader isn’t reading from the texture properly.
Below is some of the code with some commentary on the code below the code snippets.
First is a function which initializes the FBO and texture some if it I borrowed from some examples/tutorials but I believe I understand most of what each call is doing.
void generateShadowFBO()
{
GLenum FBOstatus;
// Create a shadow texture which is populated with the depth component
glGenTextures(1, &depthTextureId);
glBindTexture(GL_TEXTURE_2D, depthTextureId);
// GL_LINEAR does not make sense for depth texture. However, next tutorial shows usage of GL_LINEAR and PCF
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Remove artefact on the edges of the shadowmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
// TODO*: Have the depth precision be settable
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_DEPTH_COMPONENT,
depthTextureWidth,
depthTextureHeight,
0,
GL_DEPTH_COMPONENT,
GL_UNSIGNED_BYTE,
NULL);
glBindTexture(GL_TEXTURE_2D, 0);
// Create a FBO
glGenFramebuffers(1, &shadowFboId);
// Bind the frame buffer to the curent context and tell openGL that
// the FBO won't be writing any color information and bind the texture ID
// to the texture component of the FBO
glBindFramebuffer(GL_FRAMEBUFFER, shadowFboId);
// Instruct openGL that we won't bind a color texture with the currently binded FBO
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
// Set the texture to be at the depth attachment point of the FBO
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
depthTextureId,
0);
// check FBO status
FBOstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if( FBOstatus != GL_FRAMEBUFFER_COMPLETE )
printf("GL_FRAMEBUFFER_COMPLETE failed, CANNOT use FBO
");
// switch back to window-system-provided framebuffer
// and unbind the texture
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
Seems relatively straight forward, but maybe I’m missing something?
Now for some rendering code. First is the calls to set up the rendering to the FBO (and to the depth texture I’m assuming). The set up of the camera, etc. is correct as if I do not render to the FBO (take out the glBindFramebuffer calls and clear the depth and color bit) then the scene “renders” fine (it shows a flatly colored torus and floor).
Keep in mind I use a lot of GLTools related abstractions to speed things up, but I don’t believe those are a problem as I mentioned before that I am able to render other textures just fine, just not the one I’m supposedly writing depth information to.
// Clear depth buffer
glClear(GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, shadowFboId);
// Write depth buffer
modelViewMatrix.PushMatrix();
// Set the "camera" to be at the light's position
lightFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);
updateViewFrustumAndProjectionMatrix(depthTextureWidth, depthTextureHeight);
static GLfloat color[] = { 0.0f, 0.0f, 1.0f, 1.0f };
shaderManager.UseStockShader(
GLT_SHADER_FLAT,
transformPipeline.GetModelViewProjectionMatrix(),
color);
drawFloorAndTorusGeometry();
modelViewMatrix.PopMatrix();
// Reset frame buffer to read/write to the default window
glBindFramebuffer(GL_FRAMEBUFFER, 0);
Again, seems straight forward. I bind the framebuffer for reading and writing (I know I only need for writing…maybe I should bind it to GL_DRAW_FRAMEBUFFER instead?). I then render my scene using the “flat shader.”
Yes I know the flat shader might be a little overkill since it involves colors and yes I plan on writing my own super simple shader in the future, but I don’t think that is the problem. As mentioned before, if I don’t bind the frame buffers, the scene renders “correctly.”
So the next bit of code makes a quad, binds the texture I want to use and the shaders do the fetching of texture coordinates, etc. Again, I don’t think the shaders are an issue as other textures work fine, just not the texture I want to use (which is supposedly being written to above).
// Clear dpeth and color for "from camera" render pass
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
modelViewMatrix.PushMatrix();
viewFrustum.SetOrthographic(
0,
windowWidth,
0,
windowHeight,
1.0f,
20.0f);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
modelViewMatrix.LoadIdentity();
// Bind the depth texture
glBindTexture(GL_TEXTURE_2D, depthTextureId);
// Move back 1 unit so we can see the quad
modelViewMatrix.Translate(0, 0, -1);
shaderManager.UseStockShader(
GLT_SHADER_TEXTURE_REPLACE,
transformPipeline.GetModelViewProjectionMatrix(),
0);
quadBatch.Draw();
glBindTexture(GL_TEXTURE_2D, 0);
modelViewMatrix.PopMatrix();
I don’t there there is any issue with the “GLBatch” that I use to draw the quad because, as mentioned before, using a different texture works just fine with the same code.
So now I’m stuck, my screen is black and I don’t even know where to begin debugging. How can I check the pixels in the texture? I’ve tried using glReadPixels after binding the texture with the format GL_DEPTH_COMPONENT but that data doesn’t appear to be all 0s at all.
Any help is greatly appreciated even if it is just telling me how to debug any of this as I’m really just stuck. How can I see if the texture has the correct data short of rendering it on some geometry?
-EncodedNybble