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

Opengl es OpenGL着色器的显式与自动属性位置绑定,opengl-es,shader,opengl-es-2.0,Opengl Es,Shader,Opengl Es 2.0,为OpenGL着色器程序设置属性位置时,您将面临两个选项: glBindAttribLocation()在链接以显式定义属性位置之前 或 glGetAttriblLocation()链接以获取自动分配的属性位置后 使用其中一个的效用是什么 在实践中,哪一个(如果有的话)是首选的呢?我知道一个很好的理由,我更喜欢明确的位置定义 假设保存给定对象的几何体数据,则创建VAO的方式应使索引对应,例如: 指数0:位置 索引1:法线 索引2:texcoords 现在考虑你要画一个对象,使用两个不同的着色

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

glBindAttribLocation()在链接以显式定义属性位置之前

glGetAttriblLocation()链接以获取自动分配的属性位置后

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


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

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

假设保存给定对象的几何体数据,则创建VAO的方式应使索引对应,例如:

  • 指数0:位置
  • 索引1:法线
  • 索引2:texcoords

现在考虑你要画一个对象,使用<强>两个不同的着色器< /强>。一个着色器需要位置和法线数据作为输入,另一个-位置和纹理坐标作为输入

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

引述:

自动分配

如果前面两种方法都没有为属性索引分配输入,那么当程序链接时,OpenGL会自动分配索引。指定的索引完全是任意的,对于链接的不同程序可能不同,即使它们使用完全相同的顶点着色器代码

这意味着您将无法将VAO与两个着色器一起使用。而不是为每个(比如)对象使用一个VAO,在最坏的情况下,您需要为每个着色器为每个对象使用一个单独的VAO

通过
glBindAttribLocation
强制着色器使用您自己的属性编号约定可以轻松解决此问题-您需要做的只是保持属性与其可设置ID之间的一致关系,并强制着色器在链接时使用该约定

(如果不使用单独的VAO,这其实不是什么大问题,但仍可能使代码更清晰。)


顺便说一句:

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

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

layout(location=0) in vec4 position;

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

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

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

我看不出重点。VAO非常轻,通常会为每个帧重新创建它们。在您的情况下,您只需在调用每个着色器之前创建不同的VAO,不是吗?是的,您当然可以这样做。这也行,我们这里只讨论约定。:)第三个选项实际上在GLES2.0中可用,但格式略有不同:布局(位置=0)属性vec4位置;请注意,您还需要在GLSL文件顶部添加以下内容:#扩展名GL_EXT_separate_shader_对象:启用“VAO非常轻,通常会为每个帧重新创建它们。在您的情况下,您只需在调用每个着色器之前创建不同的VAO,不是吗?”-不,您通常不会这样做,因为这最终完全使VAOs的整个目的无效。那为什么要用VAO呢?只是一张便条。您不会将几何体数据保存在VAO中。那将是在VBO中。VAO没有数据存储。更多详细信息:谢谢,这是一个非常重要的考虑因素。据我所知,在大多数情况下,您无论如何都必须调用
glGetUniformLocation
;这个特别的考虑是否仍然相关?@MikeWeir,因为您可以设置GL 4.3。@Ruslan他们使用的是OpenGL ES。我没有在我的图形引擎中使用
glBindAttribLocation
,它在linux上运行得很好。当我移植到windows时,它使用我的法线作为顶点-我必须通过
glBindAttribLocation
明确地告诉它着色器中变量的顺序,以使其工作…正如他们所暗示的,Intel卡可能不支持这一点(而在我看来,它是完美的3.0+共振),这令人厌恶:)