【问题标题】:Reading from a depth texture in a fragment shader从片段着色器中读取深度纹理
【发布时间】:2014-02-05 11:45:26
【问题描述】:

我有一个深度纹理定义如下:

    //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();

是用Java/LWJGL/自己的小框架写的,但是思路应该很清楚。

然后我在某个时候使用片段着色器来可视化其中的数据(片段的深度):

#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);
}

我的tex_coordsshadow_tex 是正确的,但我需要进一步澄清阅读GL_DEPTH_COMPONENT32F 格式的内容。

我想读取深度,我假设它以 4 字节的浮点值存储为 0.0 和 1.0。

所以我在我可以使用texture 给我的红色通道,但是我看不出深度的差异。除了它不完全是 1.0,而是稍微低一些。如果我不除以 2.0,那么一切都是白色的。

请注意,地板在某些时候是黑色的,但这是由于阴影映射失败,因此我将其可视化 - 但是它暂时设置为使用普通视图 MVP 而不是灯光,以确保深度信息保存正确。

更新:深度值的着色现在可以正常使用以下内容:

#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);
}

我仍然想澄清一下,如果访问红色组件来检索深度值是否正确?

【问题讨论】:

    标签: java opengl shader textures depth-buffer


    【解决方案1】:

    在 GLSL 4.30 中?

      没有。

    如果这确实是深度纹理(内部格式 = GL_DEPTH_COMPONENT[...]),则 GLSL 会自动以这种方式对其进行采样:vec4 (r, r, r, 1.0)。根据“深度纹理模式”(已从 GL 3.1 / GLSL 1.30 中删除),旧版本的行为会有所不同。

    现在,如果它是您的代码所暗示的具有比较的深度纹理,那么使用sampler2D 对其进行采样应该是未定义的。但是,如果您使用 sampler2DShadow,与所有其他 texture (...) 重载(都返回 vec4)不同,使用 texture (...) 采样将返回 single float

    希望这是您粘贴的 Java 代码中的一个疏忽,因为您的着色器现在应该会产生未定义的结果。

    【讨论】:

    • 啊,也许我的代码不够清楚,我在实际从采样器中获取值之前使用了compareMode(GL_NONE),这是否澄清了事情?
    • 是的,这很有帮助。
    猜你喜欢
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多