WebGL FrameBuffer - 渲染深度纹理

时间:2014-11-15 22:50:54

标签: javascript webgl framebuffer depth-buffer webgl-extensions

我正在将后处理效果集成到我的3D引擎中。我使用带 WebGL FrameBuffer 对象捕获了深度数据。将颜色数据捕获到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 );
}

enter image description here

1 个答案:

答案 0 :(得分:4)

在设置结束时,您的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了。

如果你想使用深度纹理,我也不明白你为什么要创建深度渲染缓冲区。你应该只需要两个中的一个。如果您以后不需要它来进行采样,通常会使用渲染缓冲区作为深度。如果你想从结果中取样,你需要一个纹理,而且不再需要渲染缓冲。