WebGL FrameBuffer - визуализация текстуры глубины

Я нахожусь в процессе интеграции эффектов постобработки в мой 3D-движок. Я столкнулся с проблемой захвата данных о глубине с помощью объекта FrameBuffer с WebGL. Не было проблем с вводом данных о цвете в FrameBuffer. Тем не менее, я не могу получить данные о глубине, даже если расширение глубины включено для Chrome/Firefox.

var DepthEXT = webGLContext.getExtension( "WEBKIT_WEBGL_depth_texture" ) ||
                webGLContext.getExtension( "MOZ_WEBGL_depth_texture" );

Я пробовал много разных настроек, чтобы увидеть, была ли это проблема с конфигурацией, но независимо от того, что я пробую, я просто вижу белую текстуру. На скриншоте в конце поста показано вложение цвета, отображаемое как текстура, и вложение глубины, отображаемое как текстура. Есть ли проблема с моей инициализацией FrameBuffer, или я должен искать в другом месте, чтобы решить эту проблему?

Ниже мой код для инициализации объекта FrameBuffer:

    // Frame Buffer
    this.m_frameBuffer = gl.createFramebuffer();
    gl.bindFramebuffer( gl.FRAMEBUFFER, this.m_frameBuffer );

    // Render Buffer
    this.m_renderBuffer = gl.createRenderbuffer();
    gl.bindRenderbuffer( gl.RENDERBUFFER, this.m_renderBuffer );
    gl.renderbufferStorage( 
        gl.RENDERBUFFER,
        gl.DEPTH_COMPONENT16,
        sharedRenderer.canvasDOMElement.width,
        sharedRenderer.canvasDOMElement.height );

    // Diffuse Component
    this.m_diffuseComponentTexture = gl.createTexture();
    gl.bindTexture( gl.TEXTURE_2D, this.m_diffuseComponentTexture );

    gl.texParameteri( 
        gl.TEXTURE_2D,
        gl.TEXTURE_MAG_FILTER,
        gl.LINEAR );

    gl.texParameteri( 
        gl.TEXTURE_2D, 
        gl.TEXTURE_MIN_FILTER, 
        gl.LINEAR );

    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

    gl.texImage2D( 
        gl.TEXTURE_2D,
        0,
        gl.RGBA,
        sharedRenderer.canvasDOMElement.width,
        sharedRenderer.canvasDOMElement.height,
        0,
        gl.RGBA,
        gl.UNSIGNED_BYTE, 
        null );

    // Depth
    this.m_depthComponentTexture = gl.createTexture();
    gl.bindTexture( gl.TEXTURE_2D, this.m_depthComponentTexture );

    gl.texParameteri( 
        gl.TEXTURE_2D,
        gl.TEXTURE_MAG_FILTER,
        gl.NEAREST );

    gl.texParameteri( 
        gl.TEXTURE_2D, 
        gl.TEXTURE_MIN_FILTER, 
        gl.NEAREST );

    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

    gl.texImage2D( 
        gl.TEXTURE_2D,
        0,
        gl.DEPTH_COMPONENT,
        sharedRenderer.canvasDOMElement.width,
        sharedRenderer.canvasDOMElement.height,
        0,
        gl.DEPTH_COMPONENT,
        gl.UNSIGNED_SHORT, 
        null );

    // FrameBuffer
    // Diffuse
    gl.framebufferTexture2D( 
        gl.FRAMEBUFFER,
        gl.COLOR_ATTACHMENT0, 
        gl.TEXTURE_2D, 
        this.m_diffuseComponentTexture, 
        0 );

    // Depth
    gl.framebufferTexture2D( 
        gl.FRAMEBUFFER,
        gl.DEPTH_ATTACHMENT, 
        gl.TEXTURE_2D, 
        this.m_depthComponentTexture, 
        0 );

    // RenderBuffer
    gl.framebufferRenderbuffer( 
        gl.FRAMEBUFFER,
        gl.DEPTH_ATTACHMENT, 
        gl.RENDERBUFFER, 
        this.m_renderBuffer );


    // Unbind buffers and textures
    gl.bindTexture( gl.TEXTURE_2D, null );
    gl.bindRenderbuffer( gl.RENDERBUFFER, null );
    gl.bindFramebuffer( gl.FRAMEBUFFER, null );

Вот код, где я отрисовываю текущую сцену в FrameBuffer.

CBRenderer.prototype.renderSceneToGBuffer = function( sceneToRender, GBufferTarget, deltaSeconds )
{
        CBMatrixStack.clearMatrixStackAndPushIdentityMatrix();

        this.applyProjectionMatrix();

        GBufferTarget.bindGBufferFrameBuffer();

        this.renderer.enable( this.renderer.DEPTH_TEST );
        this.renderer.depthMask( true );
        this.renderer.clearDepth( 1.0 );
        this.renderer.clearColor( 0.1, 0.1, 0.1, 0.0 );

        this.renderer.clear( this.renderer.COLOR_BUFFER_BIT | this.renderer.DEPTH_BUFFER_BIT );

        sceneToRender.render( deltaSeconds );

        this.renderer.flush();

        GBufferTarget.m_dirty = false;
        GBufferTarget.unbindGBufferFrameBuffer();

        this.renderer.clearColor( 0.0, 0.0, 0.0, 0.0 );
        this.renderer.clear( this.renderer.COLOR_BUFFER_BIT | this.renderer.DEPTH_BUFFER_BIT );

        this.renderer.bindTexture( this.renderer.TEXTURE_2D, null );
}

введите описание изображения здесь

1 ответ

Решение

У вас нет текстуры глубины, прикрепленной к вашему FBO в конце настройки. Вы устанавливаете текстуру как привязку к глубине в некоторый момент:

// Depth
gl.framebufferTexture2D( 
    gl.FRAMEBUFFER,
    gl.DEPTH_ATTACHMENT, 
    gl.TEXTURE_2D, 
    this.m_depthComponentTexture, 
    0 );

Но сразу после этого вы устанавливаете рендер-буфер как вложенный файл глубины:

// RenderBuffer
gl.framebufferRenderbuffer( 
    gl.FRAMEBUFFER,
    gl.DEPTH_ATTACHMENT, 
    gl.RENDERBUFFER, 
    this.m_renderBuffer );

Вы можете иметь только одну цель, прикрепленную к каждой точке подключения FBO. Таким образом, второй вызов устанавливает новое вложение глубины, заменяя то, которое вы только что установили в первом вызове. Итак, в конце этого, m_depthComponentTexture больше не привязан к FBO.

Если вы хотите использовать текстуру глубины, я не понимаю, почему вы хотели бы также создать буфер визуализации глубины. Вам нужен только один из двух. Обычно вы используете рендер-буфер для глубины, если позже он вам не понадобится. Если вы хотите сэмплировать результат, вам нужна текстура, и больше нет необходимости в рендеринг-буфере.

Другие вопросы по тегам