为什么有多种方法可以将VAO传递给GLSL程序?

mpe*_*pen 6 opengl glsl

示例代码:

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)就是你需要的.

  • 哈哈哈......你是个天才!我刚刚取消了对glBindAttribLocation的调用,它运行完全一样.也许我应该联系OpenTK上的人,因为这是他们的图书馆附带的例子! (2认同)