Instancing cubes next to each other OpenGL

自古美人都是妖i 提交于 2021-02-11 07:59:12

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!