Reputation: 69259
I have a depth texture defined as the following:
//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();
It's written in Java/LWJGL/Own small framework, but the idea should be clear.
Then I use a fragment shader at some point to visualize the data in it (fragment's depth):
#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)
);
float red_channel = texture(shadow_tex, tex_coords).r;
if (red_channel < 0.999) {
red_channel = red_channel / 2.0;
}
color = vec4(vec3(red_channel), 1.0);
}
My tex_coords
and shadow_tex
are correct, but I need some more clarification on reading out of a GL_DEPTH_COMPONENT32F
format.
I want to read the depth and I assume it is being stored being 0.0 and 1.0 in 4 bytes of float values.
So I was thinking I can use the red channel of what texture
gives me back, however I cannot see a difference in depth. Other than it not being 1.0 exactly, but somewhat lower. If I do not divide by 2.0, then everything appears white.
Note that the floor is black at some points, but that is due to a failed shadow mapping, hence why I am visualizing it - however it is temporarily set to use the normal view MVP instead of the light's, to also make sure the depth information is saved correctly.
UPDATE: The colorization of the depth value is now working correctly with the following:
#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;
float linearize_depth(float original_depth) {
float near = 0.1;
float far = 1000.0;
return (2.0 * near) / (far + near - original_depth * (far - near));
}
void main(void) {
//calculate texture coordinates, based on current dimensions and positions of the viewport
vec2 tex_coords = vec2(
(gl_FragCoord.x - 100) / (screen_width / 5),
(gl_FragCoord.y - (screen_height - (screen_height / 5) - 100)) / (screen_height / 5)
);
//retrieve depth value from the red channel
float red_channel = texture(shadow_tex, tex_coords).r;
//colorize depth value, only if there actually is an object
if (red_channel < 0.999) {
red_channel = linearize_depth(red_channel) * 4.0;
}
color = vec4(vec3(red_channel), 1.0);
}
I would still like clarification though if accessing the red component is correct to retrieve the depth value?
Upvotes: 1
Views: 4128
Reputation: 43319
In GLSL 4.30?
If this is truly a depth texture (internal format = GL_DEPTH_COMPONENT[...]
), then GLSL automatically samples it this way: vec4 (r, r, r, 1.0)
. Older versions would behave differently depending on the "depth texture mode" (which was removed from GL 3.1 / GLSL 1.30).
Now, if it is a depth texture with comparison as your code implies, then sampling it using sampler2D
should be undefined. If you use sampler2DShadow
though, sampling with texture (...)
will return a single float
unlike all other texture (...)
overloads (which all return vec4
).
Hopefully this is an oversight in the Java code you pasted, because your shader should be producing undefined results as it stands right now.
Upvotes: 3