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, так что все в порядке.

Теперь я инициализирую буфер минимальной глубины, визуализируя всю геометрию с альфа-каналом ‹ 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)


person elect    schedule 26.03.2015    source источник
comment
Вы должны использовать GLBuffers.newDirectFloatBuffer() вместо FloatBuffer.allocate(), хотя в вашем случае он не является виновником. По моему скромному мнению, вам следует шаг за шагом модифицировать примерlect86, чтобы определить, какое изменение нарушает работу вашего приложения.   -  person gouessej    schedule 27.03.2015


Ответы (1)


О боже, я нашел это, в инициализации FS

uniform sampler2D opaqueDepthTexture;

должно быть

uniform sampler2DRect opaqueDepthTexture;
person elect    schedule 31.03.2015