Search code examples
javascriptwebglframebufferwebgl2

How to use a depth texture in webgl2


When you only want the color part of the frame, you can store depth in a render buffer.
This works fine for me on both webgl1 and webgl2.

When you also need to use the depth part you can't use a render buffer, you need to store it in a texture.
In webgl1 you need to get an extension to support it.
This also works fine for me in webgl1.

    const gl = canvas.getContext('webgl');
    const depthTextureExtension = gl.getExtension('WEBGL_depth_texture');
    if (!depthTextureExtension) {
        alert('Depth textures not supported');
    }

This feature should be available by default in webgl2.
Yet when I replace the code above with this:

    const gl = canvas.getContext('webgl2');

My code fails to render and I can not find any explanation why.

    this.texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);


    this.depth = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, this.depth);
    checkGLErrors(gl); // OK
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null);
    checkGLErrors(gl); // for webgl2: 1281 INVALID_VALUE
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);


    this.framebuffer = gl.createFramebuffer();
    gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, this.depth, 0);

Solution

  • In WebGL2 DEPTH_COMPONENT is not a valid internal format. Use DEPTH_COMPONENT16, DEPTH_COMPONENT24 or DEPTH_COMPONENT32F

    Example from here

      const level = 0;
      const internalFormat = gl.DEPTH_COMPONENT24;
      const border = 0;
      const format = gl.DEPTH_COMPONENT;
      const type = gl.UNSIGNED_INT;
      const data = null;
      gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
                    targetTextureWidth, targetTextureHeight, border,
                    format, type, data);