随着我对WebGL2的了解越来越多,我在着色器中遇到了这种新语法,您可以通过以下方式在着色器中设置location
:layout (location=0) in vec4 a_Position;
。与使用传统attribute
获取gl.getAttribLocation('a_Position');
位置相比,这相比如何?我认为它更快?还有其他原因吗?另外,将位置设置为整数还是可以使用字符串更好吗?
答案 0 :(得分:4)
这里有两个想法混淆
您可以在GLSL
中指定这样的位置layout (location=0) in vec4 a_Position;
您也可以像这样在
中使用JavaScript分配位置// **BEFORE** calling gl.linkProgram
gl.bindAttribLocation(program, 0, "a_Position");
在我的头脑中,似乎在JavaScript中做得更干(不要重复自己)。实际上,如果您使用一致的命名,那么在调用gl.linkProgram
之前,您可以通过仅绑定常用名称的位置来为所有着色器设置所有位置。在JavaScript中执行此操作的另一个小优势是它与GLSL ES 1.0和WebGL1兼容。
我有一种感觉,尽管在GLSL中这样做更常见。这对我来说似乎很糟糕,因为如果你遇到过冲突,你可能需要编辑10s或100s着色器。例如,您从
开始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
,这样它不会影响渲染速度,你通常只使用init的位置设置顶点数组的时间。
最好将位置设置为整数还是你也可以使用字符串?
地点是整数。您手动选择要使用的属性索引。如上所述,您可以使用替换,着色器生成,预处理器宏等...将某些类型的字符串转换为整数,但它们最终需要为整数,并且它们需要在GPU支持的属性数量范围内。你不能选择像9127这样的任意整数。只有0到N - 1,其中N是gl.getParameter(MAX_VERTEX_ATTRIBS)
返回的值。注意在WebGL2