无法使用 OpenGL 绘制多个对象
Trouble drawing multiple object with OpenGL
我正在尝试渲染多个对象,但只有指定的第一个对象正在渲染。我有一系列顶点数组,它们在单独的数组中有相应的索引。根据我读过的所有内容,我只是为每个正在绘制的对象分配 2 个 VBO——一个 VBO 用于顶点,一个用于索引。我生成缓冲区并将它们绑定到各自的 VAO。渲染时,我需要为每个对象进行单独的绘制调用。
这是我声明所需 VAO 和 VBO 的代码:
GLuint VAO[5]; // Handle for the vertex array object
GLuint VBO[10]; // Handle for the vertex buffer object
GLuint nMonumentIndices; // Number of indices of the mesh
GLuint nPlaneIndices;
GLuint nBuildingIndices;
GLuint nColumnIndices;
GLuint nPoolIndices;
这是我生成和绑定相应 VAO 和 VBO 的代码:
const GLuint floatsPerVertex = 3; // Number of coordinates per vertex
const GLuint floatsPerColor = 4; // (r, g, b, a)
// Strides between vertex coordinates is 6 (x, y, r, g, b, a). A tightly packed stride is 0.
GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);// The number of floats before each
glGenVertexArrays(5, mesh.VAO); //generates 1 vertex array
glGenBuffers(10, mesh.VBO); // generates two VBOs
glBindVertexArray(mesh.VAO[0]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[0]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(monumentVerts), monumentVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nMonumentIndices = sizeof(monumentIndices) / sizeof(monumentIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[1]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(monumentIndices), monumentIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindVertexArray(mesh.VAO[1]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[2]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVerts), planeVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nPlaneIndices = sizeof(planeIndices) / sizeof(planeIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[3]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(planeIndices), planeIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindVertexArray(mesh.VAO[2]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[4]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(monumentVerts), monumentVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nBuildingIndices = sizeof(buildingIndices) / sizeof(buildingIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[5]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(buildingIndices), buildingIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindVertexArray(mesh.VAO[3]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[6]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(columnVerts), columnVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nBuildingIndices = sizeof(columnIndices) / sizeof(columnIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[7]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(columnIndices), columnIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindVertexArray(mesh.VAO[4]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[8]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(poolVerts), poolVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nBuildingIndices = sizeof(poolIndices) / sizeof(poolIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[9]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(poolIndices), poolIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
我对正在渲染的每个对象也有单独的绘制调用:
// Activate the VBOs contained within the mesh's VAO
glBindVertexArray(gMesh.VAO[0]);
glDrawElements(GL_TRIANGLES, gMesh.nMonumentIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
glBindVertexArray(gMesh.VAO[1]);
glDrawElements(GL_TRIANGLES, gMesh.nPlaneIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
glBindVertexArray(gMesh.VAO[2]);
glDrawElements(GL_TRIANGLES, gMesh.nBuildingIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
glBindVertexArray(gMesh.VAO[3]);
glDrawElements(GL_TRIANGLES, gMesh.nColumnIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
glBindVertexArray(gMesh.VAO[4]);
glDrawElements(GL_TRIANGLES, gMesh.nPoolIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
但是渲染时,只绘制了第一个对象(纪念碑)。我哪里错了?在代码层面上,是否存在缺陷?
您不能一次绑定所有的顶点数组对象。您必须在绘制调用之前绑定正确的顶点数组对象。当前的 VAO 是一个全局状态。绑定 VAO 会破坏现有的顶点数组对象绑定。
glBindVertexArray(mesh.VAO[0]);
glDrawElements(GL_TRIANGLES, gMesh.nMonumentIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(mesh.VAO[1]);
glDrawElements(GL_TRIANGLES, gMesh.nPlaneIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(mesh.VAO[2]);
glDrawElements(GL_TRIANGLES, gMesh.nBuildingIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(mesh.VAO[3]);
glDrawElements(GL_TRIANGLES, gMesh.nColumnIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(mesh.VAO[4]);
glDrawElements(GL_TRIANGLES, gMesh.nPoolIndices, GL_UNSIGNED_SHORT, NULL);
我正在尝试渲染多个对象,但只有指定的第一个对象正在渲染。我有一系列顶点数组,它们在单独的数组中有相应的索引。根据我读过的所有内容,我只是为每个正在绘制的对象分配 2 个 VBO——一个 VBO 用于顶点,一个用于索引。我生成缓冲区并将它们绑定到各自的 VAO。渲染时,我需要为每个对象进行单独的绘制调用。
这是我声明所需 VAO 和 VBO 的代码:
GLuint VAO[5]; // Handle for the vertex array object
GLuint VBO[10]; // Handle for the vertex buffer object
GLuint nMonumentIndices; // Number of indices of the mesh
GLuint nPlaneIndices;
GLuint nBuildingIndices;
GLuint nColumnIndices;
GLuint nPoolIndices;
这是我生成和绑定相应 VAO 和 VBO 的代码:
const GLuint floatsPerVertex = 3; // Number of coordinates per vertex
const GLuint floatsPerColor = 4; // (r, g, b, a)
// Strides between vertex coordinates is 6 (x, y, r, g, b, a). A tightly packed stride is 0.
GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);// The number of floats before each
glGenVertexArrays(5, mesh.VAO); //generates 1 vertex array
glGenBuffers(10, mesh.VBO); // generates two VBOs
glBindVertexArray(mesh.VAO[0]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[0]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(monumentVerts), monumentVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nMonumentIndices = sizeof(monumentIndices) / sizeof(monumentIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[1]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(monumentIndices), monumentIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindVertexArray(mesh.VAO[1]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[2]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVerts), planeVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nPlaneIndices = sizeof(planeIndices) / sizeof(planeIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[3]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(planeIndices), planeIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindVertexArray(mesh.VAO[2]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[4]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(monumentVerts), monumentVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nBuildingIndices = sizeof(buildingIndices) / sizeof(buildingIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[5]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(buildingIndices), buildingIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindVertexArray(mesh.VAO[3]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[6]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(columnVerts), columnVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nBuildingIndices = sizeof(columnIndices) / sizeof(columnIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[7]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(columnIndices), columnIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindVertexArray(mesh.VAO[4]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[8]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(poolVerts), poolVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nBuildingIndices = sizeof(poolIndices) / sizeof(poolIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[9]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(poolIndices), poolIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
我对正在渲染的每个对象也有单独的绘制调用:
// Activate the VBOs contained within the mesh's VAO
glBindVertexArray(gMesh.VAO[0]);
glDrawElements(GL_TRIANGLES, gMesh.nMonumentIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
glBindVertexArray(gMesh.VAO[1]);
glDrawElements(GL_TRIANGLES, gMesh.nPlaneIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
glBindVertexArray(gMesh.VAO[2]);
glDrawElements(GL_TRIANGLES, gMesh.nBuildingIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
glBindVertexArray(gMesh.VAO[3]);
glDrawElements(GL_TRIANGLES, gMesh.nColumnIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
glBindVertexArray(gMesh.VAO[4]);
glDrawElements(GL_TRIANGLES, gMesh.nPoolIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
但是渲染时,只绘制了第一个对象(纪念碑)。我哪里错了?在代码层面上,是否存在缺陷?
您不能一次绑定所有的顶点数组对象。您必须在绘制调用之前绑定正确的顶点数组对象。当前的 VAO 是一个全局状态。绑定 VAO 会破坏现有的顶点数组对象绑定。
glBindVertexArray(mesh.VAO[0]);
glDrawElements(GL_TRIANGLES, gMesh.nMonumentIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(mesh.VAO[1]);
glDrawElements(GL_TRIANGLES, gMesh.nPlaneIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(mesh.VAO[2]);
glDrawElements(GL_TRIANGLES, gMesh.nBuildingIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(mesh.VAO[3]);
glDrawElements(GL_TRIANGLES, gMesh.nColumnIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(mesh.VAO[4]);
glDrawElements(GL_TRIANGLES, gMesh.nPoolIndices, GL_UNSIGNED_SHORT, NULL);