private int vbo;
private int ibo;
vbo = glGenBuffers();
ibo = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertices), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, Util.createFlippedBuffer(indices), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
//glEnableVertexAttribArray(2);
//glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, Vertex.SIZE * 4, 12);
//glVertexAttribPointer(2, 3, GL_FLOAT, false, Vertex.SIZE * 4, 20);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
//glDisableVertexAttribArray(2);
顶点着色器代码如下所示
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
out vec2 texCoord0;
uniform mat4 transform;
void main()
{
gl_Position = transform * vec4(position, 1.0);
texCoord0 = texCoord;
}
所以,这是我的理解。 glVertexAttribPointer的目的是定义顶点缓冲区对象中的数据格式。因此,在vbo中它存储数据如下
buffer.put(vertices[i].getPos().getX());
buffer.put(vertices[i].getPos().getY());
buffer.put(vertices[i].getPos().getZ());
buffer.put(vertices[i].getTexCoord().getX());
buffer.put(vertices[i].getTexCoord().getY());
buffer.put(vertices[i].getNormal().getX());
buffer.put(vertices[i].getNormal().getY());
buffer.put(vertices[i].getNormal().getZ());
因此,我们有两条glVertexAttribPointer行,因为我们在顶点着色器中定义了两个变量。因此,基本上,我们正在定义这两个变量所指向的对象。因此,第一个glVertexAttribPointer定义第一个变量“位置”是一个顶点,其中三个坐标均为浮点型。第二个glVertexAttribPointer定义了第二个变量“ texCoord”,它是一对纹理坐标,每个坐标都是浮点数。因此,如果到目前为止我的理解是正确的,那么我假设我们首先需要首先绑定顶点缓冲区对象,即使在注释掉这一行之后
glBindBuffer(GL_ARRAY_BUFFER, vbo);
它仍然有效。我很困惑。由于有两个vbo,它怎么知道我们在谈论哪个缓冲区对象?
最佳答案
@datenwolf已经在上面的评论中介绍了关键方面。详细说明:
您不必在GL_ARRAY_BUFFER
调用之前再次绑定glDrawElements()
。重要的是,当您对该属性进行glVertexAttribPointer()
调用时,绑定了要从中获取给定属性的缓冲区。
描绘这种情况的最好方法是,当您拨打此电话时:
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
您要指定告诉OpenGL从何处获取属性0(第一个参数)的数据以及如何读取数据的所有状态。该状态的大部分直接由参数给出:
它有3个组成部分
组件是浮点值
读取顶点的步幅为20个字节...
...并从缓冲区的字节0开始
但是,当您进行调用时,还有一个隐含的状态状态也存储在属性0中:
从当前绑定到
GL_ARRAY_BUFFER
的缓冲区中读取数据换句话说,与每个属性关联的状态包括属性数据来源的缓冲区的ID。这可以是多个/所有属性的相同缓冲区,也可以是每个属性的不同缓冲区。
请注意,
GL_ELEMENT_ARRAY_BUFFER
并非如此。需要在glDrawElements()
调用时绑定该对象。尽管看起来有些不一致,但这是必要的,因为索引数组没有与glVertexAttribPointer()
等效的内容。可以将API定义为具有此类调用,但是...没有。原因很可能是根本没有必要的,因为只能将一个索引数组用于绘制调用,而可以使用多个顶点缓冲区。关于opengl - 了解glVertexAttribPointer?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24876647/