OpenGL着色器的显式与自动属性位置绑定

时间:2011-01-08 20:16:29

标签: opengl-es shader opengl-es-2.0

为OpenGL着色器程序设置属性位置时,您将面临两个选项:

在链接之前

glBindAttribLocation()以明确定义属性位置。

链接后

glGetAttribLocation()以获取自动分配的属性位置。

使用其中一个的效用是什么?

在实践中,哪一个(如果有的话)是首选的?

3 个答案:

答案 0 :(得分:84)

我知道偏好显式位置定义的一个很好的理由。

考虑在Vertex Array Objects.中保存几何数据对于给定对象,您可以创建一个VAO,使得索引对应于,例如:

  • 索引0 :职位,
  • 索引1 :正常,
  • 索引2 :texcoords

现在考虑使用两个不同着色器绘制一个对象。一个着色器需要位置和普通数据作为输入,另一个 - 位置和纹理坐标

如果您编译这些着色器,您会注意到第一个着色器将预期属性索引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着色器语言中不存在。

答案 1 :(得分:17)

这里的另一个答案是glGetAttribLocation将数据返回给调用者,这意味着它隐式地需要管道刷新。如果在编译程序后立即调用它,那么实质上就是强制异步编译同步进行。

答案 2 :(得分:8)

第三个选项,即着色器代码中的layout(location=0) in vec4 position;,现在可在OpenGL ES 3.0 / GLSL 300 es中使用。仅适用于顶点着色器输入变量。