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

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

链接之前glBindAttribLocation()明确定义一个属性位置。

要么

glGetAttribLocation()链接后获得一个自动分配的属性位置。

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

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

我知道一个很好的理由,喜欢明确的位置定义。

考虑你将几何数据保存在顶点数组对象中。 对于一个给定的对象,你创build一个VAO的方式,使索引相对应,例如:

  • 索引0 :职位,
  • 索引1 :法线,
  • 索引2 :texcoords

现在考虑你想用两个不同的着色器绘制一个对象。 一个着色器需要位置和正常数据作为input,其他位置和纹理坐标

如果你编译这些着色器,你会注意到第一个着色器将会在属性索引0处的位置和在1处的法线位置。另一个将期望位置为0,但纹理坐标为1。

引用https://www.opengl.org/wiki/Vertex_Shader

自动分配

如果前两种方法都没有将input分配给属性索引,则当链接程序时,索引由OpenGL自动分配。 分配的索引是完全任意的,即使它们使用完全相同的顶点着色器代码,链接的不同程序也可能不同。

这意味着你将无法在两个着色器中使用你的VAO。 而不是每个对象都有一个VAO,在最坏的情况下,你需要为每个着色器提供一个单独的VAO

强制着色器通过glBindAttribLocation使用自己的属性编号约定可以很容易地解决这个问题 – 所有你需要做的是保持属性和他们build立的ID之间的一致关系,并强制着色器在链接时使用该约定。

(如果你不使用单独的VAO,这不是一个大问题,但仍然可能使你的代码更清晰。)


BTW:

当为OpenGL着色器程序设置属性位置时,您面临着两个select

在OpenGL / GLSL 3.3中有第三个选项:直接在着色器代码中指定位置。 它看起来像这样:

 layout(location=0) in vec4 position; 

但这在GLSL ES着色器语言中不存在。

这里的另一个答案是glGetAttribLocation将数据返回给调用者,这意味着它隐式地需要一个pipe道刷新。 如果在编译程序之后立即调用它,则基本上迫使asynchronous编译同步发生。

第三个选项,即layout(location=0) in vec4 position; 在着色器代码中,现在在OpenGL ES 3.0 / GLSL 300 es中可用。 只有顶点着色器的inputvariables。