1

So I've been trying to get shadow mapping to work, but I was unsuccessful, and I am now trying to simply write anything to the frame buffer and then render it to a quad as a texture. I've been looking at this small piece of code for 10 hours, so I thought it might finally be time to ask for some help. Do let me know if you need any more information or if something is unclear.

I started by following this tutorial. After completing it two times, and straight copy pasting a third time I gave up, and started to look elsewhere for information. My current code is a bit of a mess, but I have tried to extract what is crucial

Here is how I set up my FBO with a TEXTURE2D (_shadowMap and _shadowMapFBO are private variables in the class acting as the main program):

glGenTextures(1, &_shadowMap);
glBindTexture(GL_TEXTURE_2D, _shadowMap);
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);

glGenFramebuffers(1, &_shadowMapFBO);
glBindFramebuffer(GL_FRAMEBUFFER, _shadowMapFBO);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _shadowMap, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
{
    std::cout << "Frame buffer failed" << std::endl;
    system("pause");
    exit(1);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);

I then do the first render pass in the main loop:

glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, _shadowMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
_shadowShader.bind();
glBindVertexArray(_cubeVAO);
glDrawElements(GL_TRIANGLES, _numberOfIndicesCube, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(_planeVAO);
glDrawElements(GL_TRIANGLES, _numberOfIndicesPlane, GL_UNSIGNED_SHORT, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);

Initially I wanted to create a shadow map, but at this point I'm simply trying to write an explicit value to the entire texture attached to the frame buffer using the following shader pair (the one used by _shadowShader)

Vertex

#version 450

in layout(location=0) vec3 position;

uniform mat4 mvp;

void main()
{
    gl_Position = mvp * vec4(position, 1.0f);
}

Fragment

#version 450

out float depth;

void main()
{
    depth = 0.0f;
}

I then finish up by trying to display the texture on a quad:

glViewport(0, 0, _screenWidth, _screenHeight);
glClearColor(0.7f, 0.5f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_testShader.bind();
glBindTexture(GL_TEXTURE_2D, _shadowMap);
glBindVertexArray(_quadVAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);

Here is the fragment shader for the quad:

#version 450

in vec2 textureCoordinates;

uniform sampler2D _shadowMap;

out vec4 color;

void main()
{
    float depth = texture2D(_shadowMap, textureCoordinates).r;
    color = texture2D(_shadowMap, textureCoordinates);
}

But to my continuous frustration, the quad appears white although I output 0.0f (black) from the fragment shader...I know the quad is able to display a texture, as I've been able to render a normal texture displaying a .jpg onto it. So, this is where I'm at now; any ideas, pointers, thoughts, motivational words etc?

EDIT I: So after some more time I have at least figured out that the texture is loaded correctly and that I'm able to read from it. I did this by actually loading a image onto it during initialization and then not writing to it. The quad then displays the texture correctly. So there must be something wrong with how I'm writing to it.

EDIT II: So I got it working; I sat down with a TA and copy pasted the code (yeah, I know...doesn't get much better than that) and it now works. Thanks Bart :)

genpfault
  • 51,148
  • 11
  • 85
  • 139
MulattoKid
  • 573
  • 6
  • 14

1 Answers1

0

Your shadow pass fragment shader is just wrong:

#version 450

out float depth;

void main()
{
    depth = 0.0f;
}

This does just declare a single channel color output, which will be written to the color attachment (which you don't have). Since you want to write to the depth attachment of your FBO, you have to use the builtin gl_FragDepth output variable. If you don't do it, the GL will write the lineariliy interpolated window space depth value to the depth buffer.

Note that typically, you clear the depth buffer to 1.0, and when using a typical perspective projection, your objects would appear very close to 1.0, say at 0.99something, as the depth value, so it is very likely that converting the result to just 8 bit grayscale will look all white.

derhass
  • 43,833
  • 2
  • 57
  • 78
  • Thanks for the reply; so I actually got it working, was just about to write it. I did try what you suggest, doing gl_fragDepth = 0.2f but that didn't work either (it was before I posted this here). I got some help from one of my TA's and for some reason when he sat with me and copy pasted the code form the tutorial it worked. Thanks anyway :) – MulattoKid Nov 29 '16 at 15:37