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。