我创建了1个浮点缓冲区和1个带有我所有顶点数据(位置,纹理坐标,法线)的vbo,它们存储如下:
bf.put(vertices[i].position.x);
bf.put(vertices[i].position.y);
bf.put(vertices[i].position.z);
bf.put(vertices[i].texCoords.x);
bf.put(vertices[i].texCoords.y);
bf.put(vertices[i].normals.x);
bf.put(vertices[i].normals.y);
bf.put(vertices[i].normals.z);
如何使用glVertexAttribPointer将它们传递给着色器?
是否可以执行以下操作:
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(/*arguments for sending position*/);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(/*arguments for sending texture coordinates*/);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(/*arguments for sending normals*/);
如果是,那么请帮助我理解glVertexAttribPointer以及我应该提出的论点。
答案 0 :(得分:0)
您用于属性的数据排列通常称为" interleaved",实际上是在VBO中存储多个属性的推荐方式。它支持本地数据访问,因为顶点的所有属性在内存中彼此相邻,这反过来会导致高缓存命中率。
让我们看一下glVertexAttribPointer()
的签名,然后更详细地解释一下这些论点。我故意不会从文档中复制解释,希望替代措辞能帮助您更好地理解它们。在LWJGL中,它被定义为:
static void glVertexAttribPointer(
int index, int size, int type, boolean normalized,
int stride, long pointerOffset)
index
:顶点着色器中的顶点属性的位置,由glBindAttribLocation()
指定,使用glGetAttribLocation()
获取,或在带有location
布局的着色器代码中指定限定符。size
:属性中的组件数。例如。 3表示具有3个坐标的位置,2表示具有2个分量的纹理坐标等type
:属性类型。主要是GL_FLOAT
。normalized
:浮点属性无关紧要,如果你开始使用整数类型属性,请阅读它。stride
:后续顶点之间的字节间距。除非你在顶点之间有填充(这是相当罕见的),否则这与顶点的大小(以字节为单位)相同。pointerOffset
:这有"指针"由于历史原因,它的名称实际上是第一次出现的属性相对于缓冲区起始的字节偏移量。在交错排列中,这对应于顶点内属性的偏移量,以字节为单位。在你的情况下,stride
将是32,因为每个顶点由8个浮点组件组成,每个浮点组件为4个字节。
第一个属性的pointerOffset
为0,然后是其余所有属性的相对字节偏移量,其余两个属性的结果为12和20。
这会调用您的示例:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * 4, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * 4, 3 * 4);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * 4, (3 + 2) * 4);