【问题标题】:WebGL readPixels with Multiple Render Targets具有多个渲染目标的 WebGL readPixels
【发布时间】:2020-06-21 00:03:54
【问题描述】:

我正在使用 WebGL 1.0(扩展)和 WebGL 2.0 中的 MRT(多个渲染目标、drawBuffers 等)。

从特定绑定颜色附件中读取像素()的最佳方法是什么?

我能想到的就是制作另一个 FBO,并将我想要的纹理设置为 COLOR_ATTACHMENT0 以从中读取。

想知道是否有我没有看到的其他方法或最佳方法?

【问题讨论】:

    标签: webgl webgl2


    【解决方案1】:

    我认为没有最好的方法。在 WebGL2 中你可以使用gl.readBuffer,在 WebGL1 和 WebGL2 中你可以创建多个帧缓冲区,每个纹理一个。

    这里通过设置 readBuffer 来读取它们。

    function main() {
      const gl = document.querySelector('canvas').getContext('webgl2');
      if (!gl) {
        return alert("need WebGL2");
      }
      
      const textures = [];
      const fb = gl.createFramebuffer();
      gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
      for (let i = 0; i < 4; ++i) {
        const tex = gl.createTexture();
        textures.push(tex);
        gl.bindTexture(gl.TEXTURE_2D, tex);
        const width = 1;
        const height = 1;
        const level = 0;
        const data = new Uint8Array(4);
        data[i] = 255;
        gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, width, height, 0, 
                      gl.RGBA, gl.UNSIGNED_BYTE, data);
        // attach texture to framebuffer
        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i,
                                gl.TEXTURE_2D, tex, level);
      }
      
      // now try to read them
      for (let i = 0; i < textures.length; ++i) {
        gl.readBuffer(gl.COLOR_ATTACHMENT0 + i);
        const pixel = new Uint8Array(4);
        gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
        console.log(`${i}: ${pixel}`);
      }
    }
    main();
    <script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
    <canvas></canvas>

    并通过帧缓冲区读取它们

    function main() {
      const gl = document.querySelector('canvas').getContext('webgl2');
      if (!gl) {
        return alert("need WebGL2");
      }
      
      const textures = [];
      const fb = gl.createFramebuffer();
      gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
      for (let i = 0; i < 4; ++i) {
        const tex = gl.createTexture();
        textures.push(tex);
        gl.bindTexture(gl.TEXTURE_2D, tex);
        const width = 1;
        const height = 1;
        const level = 0;
        const data = new Uint8Array(4);
        data[i] = 255;
        gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, width, height, 0, 
                      gl.RGBA, gl.UNSIGNED_BYTE, data);
        // attach texture to framebuffer
        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i,
                                gl.TEXTURE_2D, tex, level);
      }
      
      const fbs = textures.map(tex => {
        const fb = gl.createFramebuffer();
        gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
                                gl.TEXTURE_2D, tex, 0);
        return fb;
      });
      
      // now try to read them
      for (let i = 0; i < fbs.length; ++i) {
        gl.bindFramebuffer(gl.FRAMEBUFFER, fbs[i]);
        const pixel = new Uint8Array(4);
        gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
        console.log(`${i}: ${pixel}`);
      }
    }
    main();
    <script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
    <canvas></canvas>

    【讨论】:

    • 谢谢!读取缓冲区绝对是我缺少的部分:) 一定会喜欢对一个有效的未提出问题的反对票...
    • 遗憾的是,Safari 不支持 readBuffer。所以我将使用 readBuffer 作为开始,然后回退到另一个 FBO 解决方案。对于任何想知道 readBuffer 后备的人,看起来有一篇关于此的帖子:stackoverflow.com/questions/52427194/…
    • Safari 根本不支持 WebGL2。它有一个标志,所有标志都是允许#version 300 es 着色器。截至 2020 年 6 月,所有其他 WebGL2 API 函数均未实现。请参阅 the source 并搜索“未实现”,您会看到所有 80 多个 WebGL2 均未实现。
    猜你喜欢
    • 1970-01-01
    • 2015-07-28
    • 2014-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    • 2011-11-04
    • 1970-01-01
    相关资源
    最近更新 更多