WebGL - render depth to fbo texture does not work

2019-02-04 16:24发布

For a post processing shader, I need the color and the depth buffer of my framebuffer. Accessing the colorbuffer works fine but I have problems creating the depthbuffer. I always get an INVALID_ENUM error when trying to use texImage2D for the depth texture:

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

using a renderbuffer instead of a texture works but I want depth in a texture so I can pass it to a shader.

framebuffer with depth texture code:

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);
}

2条回答
一夜七次
2楼-- · 2019-02-04 16:49

The OpenGL ES 2.0 specification (against which WebGL was specified) doesn't list GL_DEPTH_COMPONENT (or any of its sized versions) as a valid texture internal format, so it seems not to support depth textures and as the WebGL specification doesn't state anywhere that it behaves differently, it also doesn't support depth textures.

But maybe this link is of help, where depth txtures are emulated in WebGL by packing the depth value into a standard rgba texture.

查看更多
Explosion°爆炸
3楼-- · 2019-02-04 17:07

texImage2D(TEXTURE_2D, 0, DEPTH_COMPONENT16, 1536, 502, 0, DEPTH_COMPONENT, UNSIGNED_BYTE, null)

OpenGL ES has always been more restrictive in its pixel transfer parameters than desktop GL. So you have to make sure that your pixel transfer parameters match your internal format, even if you're not actually uploading any data. So try UNSIGNED_SHORT rather than UNSIGNED_BYTE.

查看更多
登录 后发表回答