opengl - 如何使用 ImageLoad() 访问深度纹理?

标签 opengl glsl

我需要在 OpenGL 计算着色器中读取深度纹理数据。

这是纹理初始化代码。

        glActiveTexture(GL_TEXTURE4);
        glGenTextures(1, &(framebufferDesc->m_DepthTextureId));
        glBindTexture(GL_TEXTURE_2D, framebufferDesc->m_DepthTextureId);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glTexImage2D(
            GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, renderWidth, renderHeight, 0, GL_DEPTH_COMPONENT,
            GL_UNSIGNED_BYTE, nullptr);

我的目标是找到“最大”深度。 1.0 或 0xffffff。

首先,我尝试一下。

//bind texture, (c++)

glBindImageTexture(2, m_EyeDesc[nEye].m_HMDDepthTextureId, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);


//access texture (glsl)
layout (local_size_x = 16, local_size_y = 16) in;

layout(binding = 0, rgba8) uniform image2D img_input;
layout(binding = 1) uniform writeonly uimage2D img_output;
layout(binding = 2, r32ui) uniform uimage2D depthMap;

void main() {
  ivec2 p = ivec2(gl_GlobalInvocationID.xy), temp_p;
  uint u_empty_color = 0xffffffff;
  //uint u_empty_color = 4294967295;

  uvec4 depth;
  depth = imageLoad(depthMap, p);

  if (u_empty_color == depth.x) {//hole
    imageStore(img_output, p, hole);
  }
}

但是上面的代码不起作用。 我尝试一些方法,将深度组件24更改为深度组件32,将0xffffffff更改为0xffffff,将r32ui更改为r32f。 但一切都失败了。

我尝试了另一种方法,成功了。

uniform sampler2D depthMap;

layout (local_size_x = 16, local_size_y = 16) in;

layout(binding = 0, rgba8) uniform image2D img_input;
layout(binding = 1) uniform writeonly uimage2D img_output;

void main() {
  ivec2 p = ivec2(gl_GlobalInvocationID.xy), temp_p;
  float u_empty_color = 1.0;

  vec2 pos = vec2(gl_GlobalInvocationID.x+1, gl_GlobalInvocationID.y+1);
  pos.x = pos.x / u_width;
  pos.y = pos.y / u_height;

  vec4 depth;
  depth = texture(depthMap, pos);


  if (u_empty_color == depth.x) {//hole
    imageStore(img_output, p, hole);
  }
} 

但是,我认为“/”太糟糕了!上面的代码很简单,真正的代码那么长......我调用了很多次。

如何访问 gl_depth_component24 格式?我不能? 请帮助我!

最佳答案

How can i access depth texture with imageLoad()?

你不能。图像加载/存储仅适用于彩色图像格式,并且根本没有与 GL_DEPTH_COMPONENT24 匹配的路径。但是,由于您无论如何都只是从图像中读取,因此也无需使用图像加载/存储。正如您自己已经注意到的,您可以简单地将其用作纹理,并从着色器中将其作为sampler2D访问。

  ivec2 p = ivec2(gl_GlobalInvocationID.xy), temp_p;
  [...]
  vec2 pos = vec2(gl_GlobalInvocationID.x+1, gl_GlobalInvocationID.y+1);
  pos.x = pos.x / u_width;
  pos.y = pos.y / u_height;

你的公式是错误的。你必须使用

vec2 pos = (vec2(p) + vec2(0.5))/vec2(u_width, u_height);

以这种方式在纹理元素中心正确采样。

but, i think '/' is so bad! upper code is simple, real code is so long... i call really many times.

我几乎不怀疑除法运算在这里完全相关,它应该完全隐藏在内存访问的延迟中。你的表现将由采样和写入决定,而你在其间进行的 ALU 操作实际上是免费的。

但是,完全没有必要经历完整的纹理采样路径。使用 texelFetch 访问带有整数坐标的未过滤纹理数据:

depth = texelFetch(depthMap, p, 0);

此外,使用计算着色器并通过图像加载/存储进行写入是否具有将全屏片段着色器传递直接渲染到目标纹理中的优势,这是非常值得怀疑的。

关于opengl - 如何使用 ImageLoad() 访问深度纹理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64004325/

相关文章:

c++ - 当启用 msaa 时,gl_FragDepth 是否等于 gl_FragCoord.z?

android - fwidth() tegra 3 glsl

JAVA OpenGL - 缩放图像以适合窗口

c++ - 为什么在尝试使用过剩回调时会出现 SIGSEGV 错误?

c - VS2015 gsl编译错误

c++ - 计算着色器 - 如何全局同步线程?

c++ - 选择模式下的 OpenGL 拾取

java - lwjgl fps绘图问题

c++ - 使用两个透明图像的深度测试会导致奇怪的伪像

opengl-es - WebGL 中的 AlphaFunctions?