问题
I tried to instance many cubes side by side each other.
My understanding is that I need to create a MVP
matrix for each cube and bind this then somehow change the position. then run this in a for loop for how many cubes you'd want.
This is what I've tried:
while (!glfwWindowShouldClose(window)) {
glClearColor(0.0f / 255.0f, 170.0f / 255.0f, 204.0f / 255.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0,
3, GL_FLOAT, GL_FALSE,
0,
(void*)0
);
computeMatricesFromInputs();
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
for (int i = 0; i == cubes; i++) {
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glDrawArraysInstanced(GL_TRIANGLES, 0, 1, i);
}
//GLuint MatrixID = glGetUniformLocation(programID, "MVP");
//glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
//glDrawArrays(GL_TRIANGLES, 0, 12*3);
glDisableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, texturebuffer);
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glfwSwapBuffers(window);
glfwPollEvents();
}
This doesn't draw any cubes at all and I can't figure out how I would change the position for each cube to be side by side each other. So why does this code not draw instanced cubes and how would I be able to change the position of each cube to rest next to each other?
回答1:
The 3rd parameter of glDrawArraysInstanced is the number of vertices you want to draw respectively of the cube (just like as glDrawArrays), the 4th is the number of instances to be drawn by 1 draw call, not the index of an instance.
Anyway You don't need glDrawArraysInstanced at all, because you draw each cube separately. Use glDrawArrays instead:
for (int i = 0; i < cubes; i++) {
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_TRIANGLES, 0, noOfVertices);
}
This can be substituted by glDrawArraysInstanced
:
glDrawArraysInstanced(GL_TRIANGLES, 0, noOfVertices, cubes);
That will draw all the cubes cubes
at once. To make that work, you have to find a way to use a different model matrix for each instance.
One possibility is to use a Shader Storage Buffer Object (SSBO), to store all the model matrices in an array. In the vertex shader the index of the instance (index of the cube) can be get by the built-in input gl_InstanceID. That variable can be used to get the proper model matrix for the instance form the array.
e.g:
layout(std430) buffer Matrices
{
mat4 mvpArray[];
};
void main()
{
mat4 mvp = mvpArray[gl_InstanceID];
// [...]
}
来源:https://stackoverflow.com/questions/61036711/instancing-cubes-next-to-each-other-opengl