示例代码:
1. glGenBuffers(1, &VboId);
2. glBindBuffer(GL_ARRAY_BUFFER, VboId);
3. glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
4. glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
5. glEnableVertexAttribArray(0);
因此,第 4 行(第一个参数(和第 5 行上的"0"表示我们选择的任意标识符/位置。在 GLSL 中,如果我们想引用这些数据,我们只需要引用相同的 ID:
layout(location=0) in vec4 in_Position;
但是,在不同的示例程序中,我看到它以不同的方式完成,没有引用"布局位置"。相反,我们做这样的事情:
1. glGenBuffers(1, &VboId);
2. glBindBuffer(GL_ARRAY_BUFFER, VboId);
3. glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
4. glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
5. glBindAttribLocation(shaderProgramHandle, 0, "in_position");
6. glEnableVertexAttribArray(0);
我们添加了一个额外的步骤 (5(,我们似乎将此属性指针绑定到特定程序中的特定变量。然后在我们的 GLSL 中,我们只是写这个:
in vec3 in_position;
不引用位置。
如果我没记错的话,这两个程序本质上做完全相同的事情......那么为什么会有差异呢?每种方法的优缺点是什么?
(我刚刚开始学习OpenGL 3.x(
没有将 VAO 传递给着色器这样的事情。VAO 只是确定如何从缓冲区对象中提取顶点属性以进行渲染。
第二个示例不执行任何操作,除非尚未链接shaderProgramHandle
。 glBindAttribLocation
位置仅在程序链接之前有效。链接程序后,无法更改其属性的获取位置。
无论如何,您真正的问题是为什么有些人使用glBindAttribLocation(..., 0)
而不是将layout(location = X)
放入着色器中。原因很简单:layout(location)
语法(相对(是新的。 glBindAttribLocation
可以追溯到GLSL的OpenGL接口的第一个版本,早在2003年左右的ARB_vertex_shader扩展中。 layout(location)
来自最近的ARB_explicit_attrib_location,它只是GL 3.3及更高版本的核心。3.3 仅在 2010 年问世。所以自然会有更多的材料谈论旧的方式。
两者的"优缺点"都很明显。从纯粹实用的角度来看,layout(location)
是新的,需要更新的驱动程序(尽管它不需要 GL 3.3。NVIDIA 的 6xxx+ 硬件支持 ARB_explicit_attrib_location,尽管只有 2.1(。 glBindAttribLocation
在源代码中工作,而layout(location)
则内置于 GLSL 着色器本身中。因此,如果您需要决定哪些属性在运行时使用哪些索引,那么使用 layout(location)
比不使用它要困难得多。但是,如果像大多数人一样,您想从着色器控制它们,那么layout(location)
就是您所需要的。