【问题标题】:Layered rendering to 3D texture using glFrameBufferTextureLayer使用 glFrameBufferTextureLayer 分层渲染到 3D 纹理
【发布时间】:2018-03-25 08:47:40
【问题描述】:

我的目标是使用gl.frameBufferTextureLayer 将切片渲染为 3D 纹理。但是,当我用gl.readPixels 读回数据时,什么都没有呈现。

当我将 gl.TEXTURE_3D 更改为 gl.TEXTURE_2D_ARRAY 时,它工作正常,但在测试中 here 他们肯定会在 FBO 上附加一层 3D 纹理。 WebGL docs 没有说明纹理应该是什么,但是 GLES3 docs 确实允许纹理成为 3D 纹理。我已经检查了帧缓冲区的完整状态和所有这些东西..

是否有任何资源可以将 3D 纹理层附加到 WebGL2 中的 FBO,这甚至可能吗?一些代码:

this.fbo= gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo);

this.colorTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_3D, this.colorTexture);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, 64, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

this.renderBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 64, 64);    
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.renderBuffer);

// Use level 1 in 3D texture
// Works when texture is GL_TEXTURE_2D_ARRAY
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, this.texture, 0, 1);

// ... Render scene

let data = new Uint8Array(64 * 64 * 4);
gl.readPixels(0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, data, 0); // data is empty

【问题讨论】:

    标签: javascript webgl rendering


    【解决方案1】:

    首先让我们尝试一个简单的不渲染

    const gl = document.createElement("canvas").getContext("webgl2");
    const fb = gl.createFramebuffer();
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    
    const tex = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_3D, tex);
    gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
    gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, 2, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    
    gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, 1);
    
    gl.clearColor(.25, .5, .75, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
    
    const data = new Uint8Array(2 * 2 * 4);
    gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
    console.log(data);

    有效

    现在让我们尝试渲染

    const gl = document.createElement("canvas").getContext("webgl2");
    const fb = gl.createFramebuffer();
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    
    const tex = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_3D, tex);
    gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
    gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, 2, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    
    gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, 1);
    
    const vs = `
    #version 300 es
    void main() {
      gl_Position = vec4(0, 0, 0, 1);
      gl_PointSize = 4.0;
    }
    `;
    
    const fs = `
    #version 300 es
    precision mediump float;
    out vec4 color;
    void main() {
      color = vec4(.75, .5, .25, 1);
    }
    `
    
    const prg = twgl.createProgram(gl, [vs, fs]);
    gl.useProgram(prg);
    gl.viewport(0, 0, 2, 2);
    gl.drawArrays(gl.POINTS, 0, 1);
    
    const data = new Uint8Array(2 * 2 * 4);
    gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
    console.log(data);
    <script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>

    这也有效。

    让我们尝试使用深度缓冲区

    const gl = document.createElement("canvas").getContext("webgl2");
    const fb = gl.createFramebuffer();
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    
    const tex = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_3D, tex);
    gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
    gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, 2, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    
    gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, 1);
    
    const rb = gl.createRenderbuffer();
    gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 2, 2);    
    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);
    
    
    const vs = `
    #version 300 es
    uniform float depth;
    void main() {
      gl_Position = vec4(0, 0, depth, 1);
      gl_PointSize = 4.0;
    }
    `;
    
    const fs = `
    #version 300 es
    precision mediump float;
    uniform vec4 color;
    out vec4 outColor;
    void main() {
      outColor = color;
    }
    `
    
    const prgInfo = twgl.createProgramInfo(gl, [vs, fs]);
    gl.useProgram(prgInfo.program);
    gl.viewport(0, 0, 2, 2);
    gl.enable(gl.DEPTH_TEST);
    
    // draw in middle
    twgl.setUniforms(prgInfo, {
      depth: 0,
      color: [1, 0, 0, 1],
    });
    gl.drawArrays(gl.POINTS, 0, 1);
    
    
    // draw in front
    twgl.setUniforms(prgInfo, {
      depth: -.5,
      color: [0, 1, 0, 1],
    });
    gl.drawArrays(gl.POINTS, 0, 1);
    
    // draw in back
    twgl.setUniforms(prgInfo, {
      depth: .5,
      color: [0, 0, 1, 1],
    });
    gl.drawArrays(gl.POINTS, 0, 1);
    
    // should be front color (0, 255, 0, 255)
    
    const data = new Uint8Array(2 * 2 * 4);
    gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
    console.log(data);
    <script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>

    似乎有效

    也许您忘记设置视口?我经常犯这个错误

    【讨论】:

    • 谢谢,这似乎确实有效。你能解释一下为什么最后一个例子没有通过深度测试吗?
    • 最后一个例子是为我通过深度测试(更新样本进行测试)。它不适合你吗?
    • 奇怪,最后一个例子对我来说都是 0。在 GTX 1070 上的最新 Chrome 和 Firefox 中测试
    • 可以确认它可以在我的 Macbook Pro 上运行。驱动程序错误? :o
    • 提交了一个错误:github.com/KhronosGroup/WebGL/issues/2618。请添加任何信息,例如您的操作系统、版本、GPU 等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多