OpenGL 绘制多个对象的正确方法?
OpenGL correct way to draw multiple objects?
我想了解如何正确绘制多个对象,为此我想逐个绘制一个立方体。问题是我显然没有做对,因为只绘制了第一张脸。我有一个 24 顶点结构(每个面 4 个顶点)和 36 个索引(每个面 6 个,每个三角形 3 个)。请随时纠正我的任何问题。
已更新
//array of vertex -- this is only the first face
Vertex vertices[24] = {
// vertex 0
{glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec2(0.0f,0.0f), glm::vec3(0.0,0.0,0.0), glm::vec3(0.0,0.0,0.0)},
// vertex 1
{glm::vec3( 1.0f, -1.0f, 1.0f), glm::vec3( 1.0f, 1.0f, 0.0f), glm::vec2(1.0f,0.0f), glm::vec3(0.0,0.0,0.0), glm::vec3(0.0,0.0,0.0)},
// vertex 2
{glm::vec3( 1.0f, 1.0f, 1.0f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec2(1.0f,1.0f), glm::vec3(0.0,0.0,0.0), glm::vec3(0.0,0.0,0.0)},
// vertex 3
{glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec2(0.0f,1.0f), glm::vec3(0.0,0.0,0.0), glm::vec3(0.0,0.0,0.0)},
unsigned int indices[36] = {
0, 2, 1, // front
2, 0, 3,
8, 10,9, // face dx
10,8,11,
12,14,13,// face sx
14,12,15,
4, 6, 5, // back face
6, 4, 7,
20,22,21,// bottom face
22,20,23,
16,18,17,// top face
18,16,19
};
// creation and population of buffers
// i am only putting here two because it's the same process for all six faces
// face 1
glGenVertexArrays(1,&global.vao0);
glGenBuffers(1,&global.vb0);
glBindVertexArray(global.vao0);
glBindBuffer(GL_ARRAY_BUFFER,global.vb0);
glGenBuffers(1,&global.ib0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,global.ib0);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*4, &vertices[0], GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*6, &indices[0], GL_STATIC_DRAW);
//face 2
glGenVertexArrays(1,&global.vao1);
glGenBuffers(1,&global.vb1);
glBindVertexArray(global.vao1);
glBindBuffer(GL_ARRAY_BUFFER,global.vb1);
glGenBuffers(1,&global.ib1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,global.ib1);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*4, &vertices[4], GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*6, &indices[6], GL_STATIC_DRAW);
那我去画他们
//my vertex struct has 5 attributes of course, but don't mind those because that's not the point
//drawing face 1
glBindVertexArray(global.vao0);
glBindBuffer(GL_ARRAY_BUFFER,global.vb0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, global.ib0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, position)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, color)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, textcoord)));
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, normal)));
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, tangent)));
global.t0.Bind(GL_TEXTURE0); // texture representing this face
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
//drawing face 2
glBindVertexArray(global.vao1);
glBindBuffer(GL_ARRAY_BUFFER,global.vb1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, global.ib1);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, position)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, color)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, textcoord)));
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, normal)));
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, tangent)));
global.t1.Bind(GL_TEXTURE0); // different texture to see if i'm drawing it correctly
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
... same thing for other faces
我做错了什么?
global.vb1
包含 4 个顶点。然而,global.ib1
中包含的索引是 8, 10, 9, 10, 8, 11。你期望什么?缓冲区中只有 4 个顶点。因此索引需要在 [0, 3].
范围内
如果将顶点拆分为 6 个缓冲区,每个缓冲区有 4 个顶点,则每个缓冲区对应的索引必须为 0, 1, 2, 0, 2, 3:
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*6, &indices[6], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,global.ib1);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*6, &indices[0], GL_STATIC_DRAW);
我想了解如何正确绘制多个对象,为此我想逐个绘制一个立方体。问题是我显然没有做对,因为只绘制了第一张脸。我有一个 24 顶点结构(每个面 4 个顶点)和 36 个索引(每个面 6 个,每个三角形 3 个)。请随时纠正我的任何问题。
已更新
//array of vertex -- this is only the first face
Vertex vertices[24] = {
// vertex 0
{glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec2(0.0f,0.0f), glm::vec3(0.0,0.0,0.0), glm::vec3(0.0,0.0,0.0)},
// vertex 1
{glm::vec3( 1.0f, -1.0f, 1.0f), glm::vec3( 1.0f, 1.0f, 0.0f), glm::vec2(1.0f,0.0f), glm::vec3(0.0,0.0,0.0), glm::vec3(0.0,0.0,0.0)},
// vertex 2
{glm::vec3( 1.0f, 1.0f, 1.0f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec2(1.0f,1.0f), glm::vec3(0.0,0.0,0.0), glm::vec3(0.0,0.0,0.0)},
// vertex 3
{glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec2(0.0f,1.0f), glm::vec3(0.0,0.0,0.0), glm::vec3(0.0,0.0,0.0)},
unsigned int indices[36] = {
0, 2, 1, // front
2, 0, 3,
8, 10,9, // face dx
10,8,11,
12,14,13,// face sx
14,12,15,
4, 6, 5, // back face
6, 4, 7,
20,22,21,// bottom face
22,20,23,
16,18,17,// top face
18,16,19
};
// creation and population of buffers
// i am only putting here two because it's the same process for all six faces
// face 1
glGenVertexArrays(1,&global.vao0);
glGenBuffers(1,&global.vb0);
glBindVertexArray(global.vao0);
glBindBuffer(GL_ARRAY_BUFFER,global.vb0);
glGenBuffers(1,&global.ib0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,global.ib0);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*4, &vertices[0], GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*6, &indices[0], GL_STATIC_DRAW);
//face 2
glGenVertexArrays(1,&global.vao1);
glGenBuffers(1,&global.vb1);
glBindVertexArray(global.vao1);
glBindBuffer(GL_ARRAY_BUFFER,global.vb1);
glGenBuffers(1,&global.ib1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,global.ib1);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*4, &vertices[4], GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*6, &indices[6], GL_STATIC_DRAW);
那我去画他们
//my vertex struct has 5 attributes of course, but don't mind those because that's not the point
//drawing face 1
glBindVertexArray(global.vao0);
glBindBuffer(GL_ARRAY_BUFFER,global.vb0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, global.ib0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, position)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, color)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, textcoord)));
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, normal)));
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, tangent)));
global.t0.Bind(GL_TEXTURE0); // texture representing this face
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
//drawing face 2
glBindVertexArray(global.vao1);
glBindBuffer(GL_ARRAY_BUFFER,global.vb1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, global.ib1);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, position)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, color)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, textcoord)));
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, normal)));
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, tangent)));
global.t1.Bind(GL_TEXTURE0); // different texture to see if i'm drawing it correctly
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
... same thing for other faces
我做错了什么?
global.vb1
包含 4 个顶点。然而,global.ib1
中包含的索引是 8, 10, 9, 10, 8, 11。你期望什么?缓冲区中只有 4 个顶点。因此索引需要在 [0, 3].
如果将顶点拆分为 6 个缓冲区,每个缓冲区有 4 个顶点,则每个缓冲区对应的索引必须为 0, 1, 2, 0, 2, 3:
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*6, &indices[6], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,global.ib1);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*6, &indices[0], GL_STATIC_DRAW);