【发布时间】:2015-03-19 11:17:40
【问题描述】:
OpenGL 函数glVertexAttribPointer 和glVertexAttribFormat 允许用户在渲染时指定将绑定到着色器程序中给定属性变量的数据格式。顶点属性格式是数据类型(int、float、byte等)、属性变量中的维数(vec2、vec3等)、数据是否应该被归一化,并且偏移到顶点数组中的数据数组的起始位置。这些函数在构建顶点数组对象 (VAO) 时指定格式,指定的格式是 VAO 状态的一部分。所以这是我的问题:
为什么要与属性关联的数据格式是VAO状态的一部分,而不是属性状态的一部分?换句话说,为什么与 VAO 相关联的数据格式而不是属性?在什么情况下我会拥有对同一属性使用不同格式的 VAO?
为了更清楚,这里有一个例子可以说明我为什么感到困惑。想象在我的顶点着色器中我声明了变量:
in vec3 position;
现在我正在我的 OpenGL 应用程序中获取属性位置:
GLint positionAttribute = glGetAttribLocation(myProgram, "position");
现在当我创建一个 VAO 时,我会像这样指定数据格式:
glVertexAttribFormat(positionAttribute, 3, GL_FLOAT, GL_FALSE, 0);
由于格式与 VAO 相关联,因此每次创建 VAO 时都必须指定格式。 'position' 属性是vec3,所以我总是指定3 和GL_FLOAT 到glVertexAttribFormat。那么为什么 OpenGL 是以这种方式设计的,所以我每次创建 VAO 时都可能必须调用glVertexAttribFormat,并指定一种保持不变的格式?在我看来,当我调用glGetAttribLocation 时,我应该指定格式,所以我只做一次。
【问题讨论】:
-
介意详细说明吗? “属性状态”是什么意思?
-
也就是说,为什么数据的格式是关联VAO而不是属性?当您调用
glVertexAttribFormat来指定数据的格式时,您需要绑定 VAO,因为该格式与 VAO 相关联。我问为什么格式不与属性本身相关联,而是。这是因为我无法想象我会为不同的数据使用不同的属性格式的场景。该属性是在着色器中静态键入的。这更清楚了吗?我可能会将此信息添加到问题中。 -
我还编辑了一个示例,希望能说明我的意思。
-
如果我没看错,你会问为什么属性设置(大小、步幅等)存储在 VAO 而不是着色器程序中。这是正确的吗?
-
在某些情况下,您应该知道 OpenGL 是有意设计的,具有不匹配顶点属性格式的能力。例如,如果您在 GLSL 中将顶点属性声明为
vec4,然后使用 1D 顶点属性指针,则在 GLSL 中您将阅读以下每个顶点(x, 0.0, 0.0, 1.0)。事实上,这就是为什么你应该总是将位置属性声明为vec4; GL 将自动为齐次w坐标分配 1.0 的值,并使您更容易编写任何矩阵变换(例如不再有像matrix * vec4 (pos, 1.0)这样的无意义的东西)。