Opengl es 在WebGL2中,布局限定符如何优于GetAttriblLocation?

Opengl es 在WebGL2中,布局限定符如何优于GetAttriblLocation?,opengl-es,webgl,webgl2,Opengl Es,Webgl,Webgl2,随着我对WebGL2的进一步了解,我在着色器中遇到了这种新语法,您可以通过在vec4 a_位置中的layout(location=0)在着色器内部设置location。这与使用传统的gl.getAttriblLocation('a_Position')获取属性位置相比如何。我想是更快吧?还有其他原因吗?另外,将位置设置为整数更好,还是也可以使用字符串更好?这里有两种想法 手动将位置指定给属性 在GLSL与JavaScript中分配属性位置 为什么要分配位置? 因为你已经知道了位置,所以你不必去查

随着我对WebGL2的进一步了解,我在着色器中遇到了这种新语法,您可以通过在vec4 a_位置中的
layout(location=0)在着色器内部设置
location
。这与使用传统的
gl.getAttriblLocation('a_Position')获取
属性
位置相比如何。我想是更快吧?还有其他原因吗?另外,将位置设置为整数更好,还是也可以使用字符串更好?

这里有两种想法

  • 手动将位置指定给属性
  • 在GLSL与JavaScript中分配属性位置
  • 为什么要分配位置?
  • 因为你已经知道了位置,所以你不必去查它
  • 您希望确保两个或多个着色器程序使用相同的位置,以便它们可以使用相同的属性。这也意味着单个顶点阵列可以与两个着色器一起使用。如果未指定属性位置,则着色器可能会对同一数据使用不同的属性。换句话说,shaderprogram1可能使用属性3表示位置,shaderprogram2可能使用属性1表示位置
  • 为什么要在GLSL中分配位置而不是在JavaScript中分配位置? 您可以在GLSL ES 3.0(而不是GLSL ES 1.0)中指定这样的位置

    您还可以像这样在JavaScript中分配一个位置

    // **BEFORE** calling gl.linkProgram
    gl.bindAttribLocation(program, 0, "a_Position");
    
    在我看来,用JavaScript做这件事似乎比较枯燥(不要重复)。事实上,如果您使用一致的命名,那么在调用
    gl.linkProgram
    之前,您可能只需绑定常用名称的位置,就可以为所有着色器设置所有位置。使用JavaScript进行此操作的另一个次要优势是它与GLSL ES 1.0和WebGL1兼容

    我有一种感觉,虽然在GLSL中这样做更常见。这对我来说很糟糕,因为如果您遇到冲突,您可能需要编辑10或100个着色器。例如,您从

    layout (location=0) in vec4 a_Position;
    layout (location=1) in vec2 a_Texcoord;
    
    稍后在另一个没有texcoord但有法线的着色器中,您可以执行此操作

    layout (location=0) in vec4 a_Position;
    layout (location=1) in vec3 a_Normal;
    
    然后,很久以后,您添加了一个着色器,该着色器需要所有3个

    layout (location=0) in vec4 a_Position;
    layout (location=1) in vec2 a_Texcoord;
    layout (location=2) in vec3 a_Normal;
    
    如果希望能够使用具有相同数据的所有3个着色器,则必须编辑前2个着色器。如果您使用JavaScript方式,就不必编辑任何着色器

    当然,另一种方法是生成常见的着色器。然后,您可以注入位置

    const someShader = `
    layout (location=$POSITION_LOC) in vec4 a_Position;
    layout (location=$NORMAL_LOC) in vec2 a_Texcoord;
    layout (location=$TEXCOORD_LOC) in vec3 a_Normal;
    ...
    `;
    
    const substitutions = {
      POSITION_LOC: 0,
      NORMAL_LOC: 1,
      TEXCOORD_LOC: 2,
    };
    const subRE = /\$([A-Z0-9_]+)/ig;
    
    function replaceStuff(subs, str) {
      return str.replace(subRE, (match, group0) => {
        return subs[group0];
      });
    }
    
    ...
    
    gl.shaderSource(prog, replaceStuff(substitutions, someShader));
    
    或者注入预处理器宏来定义它们

    const commonHeader = `
    #define A_POSITION_LOC 0
    #define A_NORMAL_LOC 1
    #define A_TEXCOORD_LOC 2
    `;
    
    const someShader = `
    layout (location=A_POSITION_LOC) in vec4 a_Position;
    layout (location=A_NORMAL_LOC) in vec2 a_Texcoord;
    layout (location=A_TEXCOORD_LOC) in vec3 a_Normal;
    ...
    `;
    
    gl.shaderSource(prog, commonHeader + someShader);
    
    速度快吗?是的,但可能不会太多,不调用
    gl.getAttribLocation
    比调用它快,但通常应在初始时间只调用
    gl.getAttribLocation
    ,这样不会影响渲染速度,并且在设置顶点数组时通常只在初始时间使用位置

    将位置设置为整数更好,还是也可以使用字符串更好


    位置是整数。您正在手动选择要使用的属性索引。如上所述,您可以使用替换、着色器生成、预处理器宏等。。。将某些类型的字符串转换为整数,但它们最终必须是整数,并且必须在GPU支持的属性数量范围内。不能选择像9127这样的任意整数。只有0到N-1,其中N是由
    gl.getParameter(MAX\u VERTEX\u ATTRIBS)
    返回的值。注:在WebGL2中,N总是>=16,这是一个非常好的答案。感谢一票给出如此详细的答案。
    const commonHeader = `
    #define A_POSITION_LOC 0
    #define A_NORMAL_LOC 1
    #define A_TEXCOORD_LOC 2
    `;
    
    const someShader = `
    layout (location=A_POSITION_LOC) in vec4 a_Position;
    layout (location=A_NORMAL_LOC) in vec2 a_Texcoord;
    layout (location=A_TEXCOORD_LOC) in vec3 a_Normal;
    ...
    `;
    
    gl.shaderSource(prog, commonHeader + someShader);