【问题标题】:Can an layout(location=n) out skip an index for drawBuffers in WebGL?布局(位置 = n)可以跳过WebGL中drawBuffers的索引吗?
【发布时间】:2021-01-06 23:58:08
【问题描述】:

我正在我的图形引擎中处理 MRT。

我正在(并旨在修复)一个有趣的点是我生成的片段着色器吐出:

layout(location = 0) out vec4 thing1;
layout(location = 2) out vec4 thing2;

应用程序端的 drawBuffers 调用如下:

gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.NONE, gl.COLOR_ATTACHMENT1]);

但是,我收到一个错误:

WebGL: INVALID_OPERATION: drawBuffers: COLOR_ATTACHMENTi_EXT or NONE

显然,这似乎是不允许的。从我从一篇讨论它的维基百科文章中读到的文档:

https://www.khronos.org/opengl/wiki/Fragment_Shader

它指出指定的布局位置是指从 drawBuffers 调用中指定的数组索引。所以,理论上我会认为这个着色器配置是有效的。

我的理解中遗漏了什么导致这不起作用?

我主要要求理解而不是修复我的程序,当我完成“正确”时,我的生成器将更正索引,而不会跳过位置索引。

更新:如下所述,您可以跳过着色器中的布局位置。我的问题是 drawBuffers 调用的格式不正确,其中只有 COLOR_ATTACHMENT2 有效的索引中有 COLOR_ATTACHMENT1。

【问题讨论】:

    标签: webgl opengl-es-2.0 webgl2 opengl-es-3.0


    【解决方案1】:

    这是错误的

    gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.NONE, gl.COLOR_ATTACHMENT1]);
    

    i 附件必须是 gl.NONEgl.COLOR_ATTACHMENTi

    应该是这样的

    gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.NONE, gl.COLOR_ATTACHMENT2]);
    

    function main() {
      const gl = document.querySelector('canvas').getContext('webgl2');
    
      const vs = `#version 300 es
      void main() {
        gl_Position = vec4(0, 0, 0, 1);
        gl_PointSize = 100.0;
      }
      `;
    
      const fs = `#version 300 es
      precision highp float;
      layout(location = 0) out vec4 thing1;
      layout(location = 2) out vec4 thing2;
      void main () {
        thing1 = vec4(1, 0, 0, 1);
        thing2 = vec4(0, 0, 1, 1);
      }
      `;
    
      const prg = twgl.createProgram(gl, [vs, fs]);
    
      const fb = gl.createFramebuffer();
      gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    
      createTextureAndAttach(gl, gl.COLOR_ATTACHMENT0);
      createTextureAndAttach(gl, gl.COLOR_ATTACHMENT2);
    
      gl.drawBuffers([
        gl.COLOR_ATTACHMENT0,
        gl.NONE,
        gl.COLOR_ATTACHMENT2,
      ]);
    
      const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
      if (status !== gl.FRAMEBUFFER_COMPLETE) {
        console.error("can't render to this framebuffer combo");
        return;
      }
    
      gl.useProgram(prg);
      gl.viewport(0, 0, 1, 1);
      gl.drawArrays(gl.POINTS, 0, 1);
      
      checkError();
      
      read(gl.COLOR_ATTACHMENT0);
      read(gl.COLOR_ATTACHMENT2);
    
      checkError();
    
      function checkError() {
        const err = gl.getError();
        if (err) {
          console.error(twgl.glEnumToString(gl, err));
        }
      }
    
      function read(attachmentPoint) {
        gl.readBuffer(attachmentPoint);
        const pixel = new Uint8Array(4);
        gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
        console.log(Array.from(pixel).join(','));
      }
    
      function createTextureAndAttach(gl, attachmentPoint) {
        const tex = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, tex);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
        gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, tex, 0);
      }
    
    }
    
    main();
    <script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
    <canvas></canvas>

    注意:为 WebGL 引用 OpenGL 文档通常是错误的和/或对 WebGL 具有误导性。您需要为 WebGL2 引用 OpenGL 3.0 ES spec

    【讨论】:

    • 谢谢!绝对是我的问题。我相信我已经知道这一点,但是在一些相当茂密的树林里把它放在一起!幸运的是,我已经做好了一切准备,所以我的引擎再次发出咕噜声:)
    猜你喜欢
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-14
    • 2012-03-02
    • 1970-01-01
    相关资源
    最近更新 更多