示例代码:
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)
答案 0 :(得分:16)
没有将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)
要困难得多。但是,如果像大多数人一样,您希望从着色器控制它们,那么{{1}}就是您所需要的。