【问题标题】:OpenGL access DepthComponent Texture in GLSL 400OpenGL 访问 GLSL 400 中的 DepthComponent Texture
【发布时间】:2017-10-31 21:45:03
【问题描述】:

我正在尝试在 400 版的 GLSL 着色器中访问深度组件纹理。

程序执行两次渲染。在第一遍中,我将所有几何图形和颜色渲染到一个帧缓冲区,在该缓冲区上我有一个 ColorAttachment 和 DepthAttachment。 DepthAttachment 绑定如下:

(注意:在我的代码示例中,我使用 C# 和 OpenTK,它是强类型的。)

GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, TextureTarget.Texture2D, depthTexture.ID, 0);

深度纹理的内部像素格式为DepthComponent32f,像素格式为DepthComponent,像素类型为Float。所有其他属性都有默认值。

第二遍使用以下着色器将帧缓冲区彩色图像渲染到屏幕上:

#version 400
uniform sampler2D finalImage;
in vec2 texCoords;
out vec4 fragColor;
void main(){
    fragColor = vec4(texture2D(finalImage, texCoords.xy).rgb, 1.0);
}

但现在我想读取深度纹理(DepthComponent)而不是颜色纹理(RGBA)。

我尝试了很多方法,例如禁用 TextureCompareMode、使用带有 shadow2DProj(sampler, vec4(texCoords.xy, 0.0, 1.0)) 或仅 textureProj(sampler, vec3(texCoords.xy, 0.0)) 的 shadow2DSampler。但它只返回 1 或 0,取决于我使用的配置。

为了确保我的深度纹理没问题,我已将像素读回浮点数组,如下所示:

GL.ReadPixels(0, 0, depthTexture.Width, depthTexture.Height, PixelFormat.DepthComponent, PixelType.Float, float_array);

一切似乎都是正确的,它向我显示 1.0 表示空白空间和 0.99 到 1.0 之间的可见对象值。

编辑 这是我的流程的代码示例:

初始化代码

depthTexture= new GLEXTexture2D(width, height);
        depthTexture.TextureCompareMode = TextureCompareMode.None;
        depthTexture.CreateMutable(PixelInternalFormat.DepthComponent32f, PixelFormat.DepthComponent, PixelType.Float);
***CreateMutable Function***
ReserveTextureID();
GLEX.glBeginTexture2D(ID);
GL.TexImage2D(TextureTarget.Texture2D, 0, pInternalFormat, width, height, 0, pFormat, pType, IntPtr.Zero);
ApplyOptions();
MarkReserved(true);
GLEX.glEndTexture2D();

(上面提到的Framebuffer附件)

渲染通道 1

GL.BindFramebuffer(FramebufferTarget.Framebuffer, drawBuffer.ID);
        GL.Viewport(0, 0, depthTexture.Width, depthTexture.Height);
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
        GL.Enable(EnableCap.DepthTest);
        GL.ClearColor(Color.Gray);
        GL.UseProgram(geometryPassShader.ID);
        geometry_shaderUniformMVPM.SetValueMat4(false, geometryImageMVMatrix * geometryImageProjMatrix);
        testRectangle.Render(PrimitiveType.QuadStrip);
        GL.UseProgram(0);
        GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);

渲染通道 2

 GL.Viewport(0, 0, depthTexture.Width, depthTexture.Height);
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
        GL.ClearColor(Color.White);
        GL.UseProgram(finalImageShader.ID);
        GL.ActiveTexture(TextureUnit.Texture0);

        depthTexture.Bind();
        final_shaderUniformMVPM.SetValueMat4(false, finalImageMatrix);
        screenQuad.Render(PrimitiveType.Quads);
        GL.UseProgram(0);
        GL.BindTexture(TextureTarget.Texture2D, 0);

【问题讨论】:

  • 从深度纹理读取与从颜色纹理读取相比没有什么特别之处。请提供一个最小的无效示例,因为无法判断您的纹理是如何绑定的等等。
  • @BDL 添加了我的流程的代码示例。不包括几何着色器,因为它只是一个基本的颜色着色器,并且使用 ReadPixels 可以正确读取深度值。
  • 不相关,但如果你在清屏后设置清色,它不会有任何效果。

标签: opengl glsl textures depth


【解决方案1】:

几个小时后,我找到了解决方案。 问题是MinFilter。就像khronos 小组在glTexParameter 上所说的那样:

GL_TEXTURE_MIN_FILTER 的初始值为GL_NEAREST_MIPMAP_LINEAR

我将深度纹理的 MinFilter 更改为 GL_NEAREST(其中 GL_LINEAR 也是合法的),现在 GLSL 着色器中的深度值是正确的(当然是在线性化之后)。

附加信息: MagFilter 有一些扩展,例如 LINEAR_DETAIL_ALPHA_SGIS。我已经尝试了其中的一些,深度值的正确性没有受到影响。

【讨论】:

  • 如果有问题请评论我的回答。如果一切正常,我会将其标记为答案。
猜你喜欢
  • 1970-01-01
  • 2021-01-05
  • 1970-01-01
  • 2013-07-12
  • 2011-06-30
  • 2021-11-05
  • 1970-01-01
  • 2012-04-16
相关资源
最近更新 更多