通过一次绘制调用绘制数千个基元

时间:2016-07-23 18:42:29

标签: c++ opengl

我想通过一次绘制调用渲染100,000多个立方体(由36个顶点构成,在同一个VAO中使用索引几何体),这可能吗?

所有几何数据(顶点数据)都是相同的,因为它们都是立方体。投影和摄像机视图也相同,并作为制服传递到顶点着色器。

Render.cpp

for (auto chunk : world->chunks) {
    for (auto cube : chunk.blocks) {
        glBindTexture(GL_TEXTURE_CUBE_MAP, textures[cube.texture]);

        // Model - transform_z * transform_y * transform_x * transform_translation * transform_scaling
        model = Mat4<GLfloat>();
        model = model.translate(cube.position);
        model = model.scale(cube.scale);
        model = model * transformation_matrix_x(cube.theta_x);
        model = model * transformation_matrix_y(cube.theta_y);
        model = model * transformation_matrix_z(cube.theta_z);
        glUniformMatrix4fv(gl_model, 1, GL_TRUE, model.data());
        // One draw call per cube is not scalable
        glDrawElements(GL_TRIANGLES, cube.indices.size(), GL_UNSIGNED_INT, 0);
    }
    // A draw call like this would be nice since they share so much data.
    // glDrawLotsOfElements(GL_TRIANGLES, cube.indices.size() * numCubes, GL_UNSIGNED_INT, 0);
}

顶点着色器

#version 330 core

in vec3 position;
in vec4 vColor;

out vec4 fColor;
out vec3 fTexcoord;

// Model
uniform mat4 model;

// View or a.k.a camera matrix
uniform mat4 camera_view;

// Projection 
uniform mat4 projection;

void main() {
  gl_Position = projection * camera_view * model * vec4(position, 1.0f);
  fColor = vColor;
  fTexcoord = normalize(position);
}

如果重要的话,立方体的数量是动态的。

1 个答案:

答案 0 :(得分:0)

我在渲染粒子时使用过实例渲染,所以我们会看看这是否能指向正确的方向。

在游戏循环之前,您将调用渲染场景的功能。在该功能中,您可以像这样设置模型矩阵,这样您就可以将每个立方体放在世界的不同位置:

# Save Compressed Images
IMAGES=`grep '^\s*image' docker-compose.yml | sed 's/image://' | sort | uniq`

docker save $IMAGES | gzip > images.tar.gz

# Load Compressed Images
gunzip -c images.tar.gz | docker load

然后,您将进入一个循环,您将为每个立方体赋予不同的位置

//matrices for the cubes
//set amount by the number of cubes you want to draw
glm::mat4* modelMatrices;
modelMatrices = new glm::mat4[amount];

现在填充缓冲区时看起来有点不同,因为你必须将模型矩阵(mat4)作为属性发送到GPU端,所以你需要4个顶点属性指针,而且不要忘了

for (GLuint i = 0; i < amount; i++)
{    //use a function like rand() to get the x,y,z values different
     glm::mat4 model;
     model = glm::translate(model, glm::vec3(x, y, z));
     modelMatrices[i] = model;
}

最后

        glVertexAttribDivisor(1, 1);
        glVertexAttribDivisor(2, 1);
        glVertexAttribDivisor(3, 1);
        glVertexAttribDivisor(4, 1);

然后,当您实际渲染多维数据集时,您将不得不再次使用glDrawArraysInstanced(GL_POINTS, 0, 1, amount); //replace to specify for a cube

在GPU方面,您只需要使用之前发送的模型矩阵替换通常的模型矩阵。