在为 OpenGL 着色器程序设置属性位置时,您面临两个选择:
glBindAttribLocation()在链接之前明确定义一个属性位置。
或者
glGetAttribLocation()链接后获取一个自动分配的属性位置。
使用其中一个的实用程序是什么?
如果有的话,哪一个在实践中更受欢迎?
在为 OpenGL 着色器程序设置属性位置时,您面临两个选择:
glBindAttribLocation()在链接之前明确定义一个属性位置。
或者
glGetAttribLocation()链接后获取一个自动分配的属性位置。
使用其中一个的实用程序是什么?
如果有的话,哪一个在实践中更受欢迎?
我知道一个很好的理由更喜欢明确的位置定义。
考虑将几何数据保存在Vertex Array Objects 中。对于给定的对象,您以索引对应的方式创建 VAO,例如:
现在考虑您想用两个不同的着色器绘制一个对象。一个着色器需要位置和法线数据作为输入,另一个需要位置和纹理坐标。
如果您编译这些着色器,您会注意到第一个着色器期望属性索引为 0 的位置和法线索引为 1。另一个着色器期望位置为 0,但纹理坐标为 1。
引用https://www.opengl.org/wiki/Vertex_Shader:
自动分配
如果前两种方法都没有为属性索引分配输入,则该索引由 OpenGL 在程序链接时自动分配。分配的索引是完全任意的,并且对于链接的不同程序可能不同,即使它们使用完全相同的顶点着色器代码。
这意味着您将无法将您的 VAO 与两个着色器一起使用。不是每个对象都有一个 VAO,而是需要 - 在最坏的情况下 -每个着色器每个对象都有一个单独的 VAO。
通过强制着色器使用您自己的属性编号约定glBindAttribLocation
可以轻松解决此问题 - 您需要做的就是保持属性与其已建立的 ID 之间的一致关系,并在链接时强制着色器使用该约定。
(如果您不使用单独的 VAO,这并不是一个真正的大问题,但仍然可能使您的代码更清晰。)
顺便提一句:
在为 OpenGL 着色器程序设置属性位置时,您面临两个选择
OpenGL/GLSL 3.3 中还有第三个选项:直接在着色器代码中指定位置。它看起来像这样:
layout(location=0) in vec4 position;
但这在 GLSL ES 着色器语言中不存在。
这里的另一个答案是 glGetAttribLocation 将数据返回给调用者,这意味着它隐含地需要管道刷新。如果您在编译程序后立即调用它,您实际上是在强制异步编译同步发生。
第三个选项,即layout(location=0) in vec4 position;
在着色器代码中,现在在 OpenGL ES 3.0/GLSL 300 es 中可用。仅适用于顶点着色器输入变量。