在 GLSL 着色器中采样 GL_DEPTH_COMPONENTs 类型 GL_UNSIGNED_SHORT

sampling GL_DEPTH_COMPONENTs of type GL_UNSIGNED_SHORT in GLSL shader

我可以访问深度相机的输出。我想使用计算着色器在 opengl 中将其可视化。

深度馈送以帧的形式给出,我提前知道宽度和高度。如何在着色器中对纹理进行采样并检索深度值?这可能吗?我已经通读了 OpenGl 类型 here,但在未签名的短裤上找不到任何东西,所以我开始担心了。有什么解决方法吗?

我当前的计算着色器

#version 430
layout(local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, binding = 0) uniform image2D img_output;


uniform float width;
uniform float height;
uniform sampler2D depth_feed;

void main() {
  // get index in global work group i.e x,y position
  vec2 sample_coords = ivec2(gl_GlobalInvocationID.xy) / vec2(width, height);

  float visibility = texture(depth_feed, sample_coords).r;

  vec4 pixel = vec4(1.0, 1.0, 0.0, visibility);

  // output to a specific pixel in the image
  imageStore(img_output, ivec2(gl_GlobalInvocationID.xy), pixel);
}

深度纹理定义如下:

glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, width, height, 0,GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, nullptr);

目前我的代码生成纯黄色屏幕。

如果使用透视投影,则深度值不是线性的。参见 LearnOpenGL - Depth testing

如果所有深度值都接近 0.0,并且您使用以下表达式:

vec4 pixel = vec4(vec3(visibility), 1.0);

那么所有的像素几乎都是黑色的。其实像素也不是全黑的,只是差别不大。

当远平面“太”远时,就会发生这种情况。验证你可以计算1.0 - visibility的幂,让不同的深度值可以被识别。例如:

float exponent = 5.0;
vec4 pixel = vec4(vec3(pow(1.0-visibility, exponent)), 1.0);

如果您想要更复杂的解决方案,您可以按照 How to render depth linearly in modern OpenGL with gl_FragCoord.z in fragment shader? 的答案中的说明线性化深度值。

请注意,为了获得令人满意的可视化效果,您应该使用深度缓冲区的整个范围 ([0.0, 1.0])。几何体必须在近平面和远平面之间,但尽量将近平面和远平面移动到尽可能靠近几何体的位置。