OpenGL着色器的显式和自动属性位置绑定
为OpenGL着色器程序设置属性位置时,您面临两个选择:
链接前glBindAttribLocation()明确定义属性位置。
要么
glGetAttribLocation()链接后获得一个自动分配的属性位置。
使用其中一个的效用是什么?
如果有的话,哪一个在实践中更受欢迎?
我知道有一个很好的理由喜欢明确的位置定义。
考虑您将几何数据保存在顶点数组对象中。 对于一个给定的对象,你创建一个VAO的方式使索引符合,例如:
现在考虑你想用两种不同的着色器绘制一个对象。 一个着色器需要位置和正常数据作为输入,其他位置和纹理坐标 。
如果你编译了这些着色器,你会注意到第一个着色器会预期位于属性索引0和位置为1的位置。另一个位置的位置为0,但纹理坐标位于1。
引用https://www.opengl.org/wiki/Vertex_Shader:
自动分配
如果前两种方法都没有将输入分配给属性索引,则当链接程序时,索引由OpenGL自动分配。 分配的索引完全是任意的,对于链接的不同程序可能不同,即使它们使用完全相同的顶点着色器代码。
这意味着你将无法在两个着色器中使用你的VAO。 而不是每个对象都有一个VAO,您需要 - 在最坏的情况下 - 每个着色器需要一个单独的VAO 。
强制着色器通过glBindAttribLocation
使用自己的属性编号约定可以轻松解决这个问题 - 您只需要在属性与其建立的ID之间保持一致的关系,并强制着色器在链接时使用该约定。
(如果你不使用单独的VAO,这并不是一个大问题,但仍然可能使你的代码更加清晰。)
BTW:
为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中使用。 但只适用于顶点着色器输入变量。
上一篇: Explicit vs Automatic attribute location binding for OpenGL shaders