0
votes

I am trying to implement shadow mapping for a few days now and I think I am starting to see the real issue at hand: I have an FBO with a Depth Texture attached to it, for the light pass of shadow mapping, however nothing is being rendered in it. Not even hardcoded values.

I have double checked the part of the program that visualizes the depth texture, and that is working with regular textures, moreover I see no shadows appearing in my scene, so I think something is definately wrong.

init:

    //shadow FBO and texture
    depthFBO = new FrameBufferObject().create().bind();
    depthTexture = new Texture2D().create().bind()
            .storage2D(12, GL_DEPTH_COMPONENT32F, 4096, 4096)
            .minFilter(GL_LINEAR)
            .magFilter(GL_LINEAR)
            .compareMode(GL_COMPARE_REF_TO_TEXTURE)
            .compareFunc(GL_LEQUAL);
    depthFBO.texture2D(GL_DEPTH_ATTACHMENT, GL11.GL_TEXTURE_2D, depthTexture, 0)
            .checkStatus().unbind();
    depthTexture.unbind();

render:

    depthFBO.bind();
    glViewport(0, 0, 4096, 4096);
    glEnable(GL_POLYGON_OFFSET_FILL);
    glPolygonOffset(4.0f, 4.0f);
    glDrawBuffer(GL_NONE);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClearDepthf(1f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    Drawable.drawAllLightPass(drawables, lightNormalProgram, lightTessellationProgram);
    glDisable(GL_POLYGON_OFFSET_FILL);
    depthFBO.unbind();

Code in direct gl* calls.

init:

int frameBufferObjectId = GL30.glGenFramebuffers();
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferObjectId);

int textureId = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId);
GL42.glTexStorage2D(GL11.GL_TEXTURE_2D, 12, GL_DEPTH_COMPONENT32F, 4096, 4096);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);

GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL11.GL_TEXTURE_2D, textureId, 0);
if (GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER) != GL30.GL_FRAMEBUFFER_COMPLETE) {
    throw new RuntimeException(this + " is not complete.");
}
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);

render:

GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferObjectId);
glViewport(0, 0, 4096, 4096);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(4.0f, 4.0f);
glDrawBuffer(GL_NONE);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepthf(1f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//appropiate calls to glDraw* are being done, this is confirmed to work as it works for displaying data

glDisable(GL_POLYGON_OFFSET_FILL);
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);

Now the most important shaders:

light-normal.vs.glsl

#version 430 core

layout(location = 4) uniform mat4 light_model_matrix;
layout(location = 5) uniform mat4 light_view_matrix;
layout(location = 6) uniform mat4 light_projection_matrix;

layout(location = 0) in vec4 position;

void main(void) {
    gl_Position = light_projection_matrix * light_view_matrix * light_model_matrix * position;
}

light-normal.fs.glsl

#version 430 core

layout(location = 0) out float depth;

void main(void) {
    depth = gl_FragCoord.z;
}

Also even hardcoding depth to either 0.0f, 0.5f or 1.0f neither work.

Just to clarify if my expectations are correct: When I move my camera close to an object that is being rendered on the screen, then the color of the depth buffer should change? As depth will be close to 0.0f then, and far away from 1.0f?

Also another clarification: What I see as the depth-values, is a rectangle that is colored white everywhere.

As per request, shaders to visualize the depth texture data:

depth-box.vs.glsl

#version 430 core

void main(void) {
    const vec4 vertices[6] = vec4[](
        vec4(-1.0, -1.0, 1.0, 1.0),
        vec4(-1.0, 1.0, 1.0, 1.0),
        vec4(1.0, 1.0, 1.0, 1.0),

        vec4(1.0, 1.0, 1.0, 1.0),
        vec4(1.0, -1.0, 1.0, 1.0),
        vec4(-1.0, -1.0, 1.0, 1.0)
    ); 

    gl_Position = vertices[gl_VertexID];
}

depth-box.fs.glsl

#version 430 core

layout(location = 7) uniform int screen_width;
layout(location = 8) uniform int screen_height;

layout(binding = 0) uniform sampler2D shadow_tex;

out vec4 color;

void main(void) {
    vec2 tex_coords = vec2(
        (gl_FragCoord.x - 100) / (screen_width / 5),
        (gl_FragCoord.y - (screen_height - (screen_height / 5) - 100)) / (screen_height / 5)
    );
    color = vec4(vec3(texture(shadow_tex, tex_coords).r), 1.0);
}
1

1 Answers

1
votes

This is not going to work, you forgot to disable texture comparison. You cannot sample a texture with a texutre comparison mode other than GL_NONE using sampler2D. The results will be undefined.

sampler2DShadow is necessary to read a texture with comparison enabled. And when you do this, the first two texture coordinates work as normal but the third is the depth value to compare against and the return of texture (...) is a floating-point value (1.0 for pass, 0.0 for fail). It can be somewhere inbetween if you have a linear filter.