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

  • 本文关键字:VAO 程序 GLSL 方法 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);

因此,第 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 只是确定如何从缓冲区对象中提取顶点属性以进行渲染。

第二个示例不执行任何操作,除非尚未链接shaderProgramHandleglBindAttribLocation位置仅在程序链接之前有效。链接程序后,无法更改其属性的获取位置。

无论如何,您真正的问题是为什么有些人使用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)就是您所需要的。

最新更新