示例代码:
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);
Run Code Online (Sandbox Code Playgroud)
所以第4行(第一个参数)和5的"0"指的是我们选择的任意标识符/位置.在GLSL中,如果我们想要引用这些数据,我们只需要引用相同的ID:
layout(location=0) in vec4 in_Position;
Run Code Online (Sandbox Code Playgroud)
但是,在一个不同的示例程序中,我看到它以不同的方式完成,没有引用"布局位置".相反,我们这样做:
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);
Run Code Online (Sandbox Code Playgroud)
我们添加了一个额外的步骤(5),我们似乎将此属性指针绑定到特定程序中的特定变量.然后在我们的GLSL中我们只写下这个:
in vec3 in_position;
Run Code Online (Sandbox Code Playgroud)
没有参考位置.
如果我没有弄错的话,这两个程序基本上完全相同......那么为什么会有区别呢?每种方法的优缺点是什么?
(我刚开始学习OpenGL 3.x)
Nic*_*las 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)
就是你需要的.