WebGL - 渲染深度到fbo纹理无法工作

12

我需要使用一个处理后的着色器来获取我的帧缓冲区的颜色和深度缓冲区。访问颜色缓冲区可以正常运行,但是我在创建深度缓冲区时遇到问题。每当我尝试使用texImage2D函数创建深度纹理时,都会出现INVALID_ENUM错误:

WebGL error INVALID_ENUM in texImage2D(TEXTURE_2D, 0, DEPTH_COMPONENT16, 1536, 502, 0, DEPTH_COMPONENT, UNSIGNED_BYTE, null)

使用渲染缓冲而不是纹理可以工作,但我想在一个纹理中获得深度,以便可以将其传递给着色器。

带有深度纹理的帧缓冲代码:

Framebuffer.prototype.initBufferStuffTexture = function(width, height){
    if(this.width == width && this.height == height){
        return;
    }

    this.width = width;
    this.height = height;

    // remove existing buffers
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    if(this.texture != null){
        gl.deleteTexture(this.texture.glid);
        this.texture = null;
    }
    if(this.renderbuffer != null){
        gl.deleteRenderbuffer(this.renderbuffer);
        this.renderbuffer = null;
    }
    if(this.framebuffer != null){
        gl.deleteFramebuffer(this.framebuffer);
        this.framebuffer = null;
    }

    // create new buffers
    this.framebuffer = gl.createFramebuffer();
    this.texture = new Texture();
    this.texture.glid = gl.createTexture();
    this.depth = new Texture();
    this.depth.glid = gl.createTexture();

    // framebuffer
    gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
    this.framebuffer.width = width;
    this.framebuffer.height = height;

    // colorbuffer
    gl.bindTexture(gl.TEXTURE_2D, this.texture.glid);
    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.RGBA, this.framebuffer.width, this.framebuffer.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

    // depthbuffer
    gl.bindTexture(gl.TEXTURE_2D, this.depth.glid);
    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_COMPONENT16, this.framebuffer.width, this.framebuffer.height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_BYTE, null);

    // assemble buffers
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.glid, 0);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, this.depth.glid, 0);

    this.checkBuffer();

    gl.bindTexture(gl.TEXTURE_2D, null);
    gl.bindRenderbuffer(gl.RENDERBUFFER, null);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
}
1个回答

9
OpenGL ES 2.0规范(WebGL的规范)不将GL_DEPTH_COMPONENT(或其任何大小版本)列为有效的纹理内部格式,因此似乎不支持深度纹理。由于WebGL规范没有声明它的行为有所不同,因此也不支持深度纹理。但也许这个链接会有所帮助,在这里,通过将深度值打包到标准RGBA纹理中,可以在WebGL中模拟深度纹理。

谢谢指出。如果我理解正确的话,获取深度信息的唯一方法是添加另一个渲染通道,使用输出深度值作为rgba值的着色器将整个场景渲染到rgba纹理中。我想我必须放弃后期处理。只渲染一次场景需要太长时间了,我无法承担将其渲染两次的代价。它由几百万个点组成。 - Markus
@Markus 你也可以使用多个渲染目标(在带有多个颜色附件的FBO中进行渲染,从片段着色器中因此写入多个颜色),但我不知道WebGL支持到什么程度。 - Christian Rau
有关 mrts 的帖子说这是不可能的,规范只定义了“COLOR_ATTACHMENT0”。真可惜,那本来是一个不错的功能。 - Markus
6
现在 WEBKIT_WEBGL_depth_texture 扩展得到了广泛的支持。 - Will
链接是404。请更新。 - DavidsKanal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接