GLSL,在有界深度纹理的片段着色器中读取错误的值



我正在应用经典深度剥离算法的一个稍微修改过的版本,基本上我首先渲染所有不透明的对象,然后使用该深度作为最小深度,因为它们是不透明的,所以不丢弃比它们更深的碎片是没有意义的。

我首先在一个小的测试用例中测试了它,它运行得非常完美。

现在我正在将该算法应用于我的主要应用程序,但由于一些未知的原因,它不起作用,我快疯了,主要问题是我一直在读取下一阶段的碎片着色器中限定的不透明深度纹理的值0

总之,这就是不透明材料的fbo:

opaqueDepthTexture = new int[1];
opaqueColorTexture = new int[1];
opaqueFbo = new int[1];
gl3.glGenTextures(1, opaqueDepthTexture, 0);
gl3.glGenTextures(1, opaqueColorTexture, 0);
gl3.glGenFramebuffers(1, opaqueFbo, 0);
gl3.glBindTexture(GL3.GL_TEXTURE_RECTANGLE, opaqueDepthTexture[0]);
gl3.glTexImage2D(GL3.GL_TEXTURE_RECTANGLE, 0, GL3.GL_DEPTH_COMPONENT32F, width, height, 0,
        GL3.GL_DEPTH_COMPONENT, GL3.GL_FLOAT, null);
gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_BASE_LEVEL, 0);
gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_MAX_LEVEL, 0);
gl3.glBindTexture(GL3.GL_TEXTURE_RECTANGLE, opaqueColorTexture[0]);
gl3.glTexImage2D(GL3.GL_TEXTURE_RECTANGLE, 0, GL3.GL_RGBA, width, height, 0,
        GL3.GL_RGBA, GL3.GL_FLOAT, null);
gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_BASE_LEVEL, 0);
gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_MAX_LEVEL, 0);
gl3.glBindFramebuffer(GL3.GL_FRAMEBUFFER, opaqueFbo[0]);
gl3.glFramebufferTexture2D(GL3.GL_FRAMEBUFFER, GL3.GL_DEPTH_ATTACHMENT, GL3.GL_TEXTURE_RECTANGLE,
        opaqueDepthTexture[0], 0);
gl3.glFramebufferTexture2D(GL3.GL_FRAMEBUFFER, GL3.GL_COLOR_ATTACHMENT0, GL3.GL_TEXTURE_RECTANGLE,
        opaqueColorTexture[0], 0);
checkBindedFrameBuffer(gl3);

在这里,我只是清除深度(默认为1),我甚至注释掉了不透明的渲染:

        /**
         * (1) Initialize Opaque FBO.
         */
        gl3.glBindFramebuffer(GL3.GL_FRAMEBUFFER, opaqueFbo[0]);
        gl3.glDrawBuffer(GL3.GL_COLOR_ATTACHMENT0);
        gl3.glClearColor(1, 1, 1, 1);
        gl3.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT);
        gl3.glEnable(GL3.GL_DEPTH_TEST);
        dpOpaque.bind(gl3);
        {
//            EC_Graph.instance.getRoot().renderDpOpaque(gl3, dpOpaque, new MatrixStack(), properties);
        }
        dpOpaque.unbind(gl3);

我有来自的双重确认

FloatBuffer fb = FloatBuffer.allocate(1 * GLBuffers.SIZEOF_FLOAT);
gl3.glReadPixels(width / 2, height / 2, 1, 1, GL3.GL_DEPTH_COMPONENT, GL3.GL_FLOAT, fb);
System.out.println("opaque fb.get(0) " + fb.get(0));

例如,如果我将clearDepth更改为0.9,我会得到0.9,所以这是可以的

现在,我通过渲染所有具有alpha<1和我将之前的深度纹理(不透明渲染中使用的深度纹理)绑定到

uniform sampler2D opaqueDepthTexture;

我暂时将这篇文章的渲染切换到默认的帧缓冲区

        /**
         * (2) Initialize Min Depth Buffer.
         */
        gl3.glBindFramebuffer(GL3.GL_FRAMEBUFFER, 0);
        gl3.glDrawBuffer(GL3.GL_BACK);
//        gl3.glBindFramebuffer(GL3.GL_FRAMEBUFFER, blendFbo[0]);
//        gl3.glDrawBuffer(GL3.GL_COLOR_ATTACHMENT0);
        gl3.glClearColor(0, 0, 0, 1);
        gl3.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT);
        gl3.glEnable(GL3.GL_DEPTH_TEST);
        if (cullFace) {
            gl3.glEnable(GL3.GL_CULL_FACE);
        }
        dpInit.bind(gl3);
        {
            gl3.glActiveTexture(GL3.GL_TEXTURE1);
            gl3.glBindTexture(GL3.GL_TEXTURE_RECTANGLE, opaqueDepthTexture[0]);
            gl3.glUniform1i(dpInit.getOpaqueDepthTextureUL(), 1);
            gl3.glBindSampler(1, sampler[0]);
            {
                EC_Graph.instance.getRoot().renderDpTransparent(gl3, dpInit, new MatrixStack(), properties);
            }
            gl3.glBindTexture(GL3.GL_TEXTURE_RECTANGLE, 0);
            gl3.glBindSampler(1, 0);
        }
        dpInit.unbind(gl3);

这是dpInit片段着色器:

#version 330
out vec4 outputColor;
uniform sampler2D texture0;
in vec2 oUV;
uniform sampler2D opaqueDepthTexture;
/*
*   Layout {lighting, normal orientation, active, selected}
*/
uniform ivec4 settings;
const vec3 selectionColor = vec3(1, .5, 0);
const vec4 inactiveColor = vec4(.5, .5, .5, .2);
vec4 CalculateLight();
void main()
{
    float opaqueDepth = texture(opaqueDepthTexture, gl_FragCoord.xy).r;
    if(gl_FragCoord.z > opaqueDepth) {        
        //discard;
    }
    vec4 color = (1 - settings.x) * texture(texture0, oUV) + settings.x * CalculateLight();
    if(settings.w == 1) {
        if(settings.z == 1) {
            color = vec4(selectionColor, color.q);
        } else {
            color = vec4(selectionColor, inactiveColor.w);
        }
    } else {
        if(settings.z == 0) {
            color = inactiveColor;
        }
    }
    outputColor = vec4(color.rgb * color.a, 1.0 - color.a);
    outputColor = vec4(.5, 1, 1, 1.0 - color.a);
    if(opaqueDepth == 0)
        outputColor = vec4(1, 0, 0, 1);
    else
        outputColor = vec4(0, 1, 0, 1);
}

忽略中间,重要的是在开始时,我读取上一个深度纹理的红色分量,然后在结束时进行比较,我获得的几何体是红色的,这意味着我在opaqueDepthTexture中读取的值是0…

问题是为什么?

在dpInit渲染之后,如果我再次绑定opaqueFbo并读取深度,它总是clearDepth,因此默认值为1,如果我用.9清除它,则为.9,因此它可以工作。

实际上,问题是我在绑定深度纹理的dpInit FS中读取了错误的值。。为什么?

为了澄清,这是采样器:

private void initSampler(GL3 gl3) {
    sampler = new int[1];
    gl3.glGenSamplers(1, sampler, 0);
    gl3.glSamplerParameteri(sampler[0], GL3.GL_TEXTURE_WRAP_S, GL3.GL_CLAMP_TO_EDGE);
    gl3.glSamplerParameteri(sampler[0], GL3.GL_TEXTURE_WRAP_T, GL3.GL_CLAMP_TO_EDGE);
    gl3.glSamplerParameteri(sampler[0], GL3.GL_TEXTURE_MIN_FILTER, GL3.GL_NEAREST);
    gl3.glSamplerParameteri(sampler[0], GL3.GL_TEXTURE_MAG_FILTER, GL3.GL_NEAREST);
}

Ps:检查所有组件,我看到opaqueDepthTexture总是有以下值(0,0,0和1)

天哪,我在init FS 中找到了它

uniform sampler2D opaqueDepthTexture;

应该是

uniform sampler2DRect opaqueDepthTexture;

最新更新