I'm making a 3D voxel game to learn OpenGL (think Minecraft). I know that rendering each face of each cube is slow, so I'm working on meshing. My meshing algorithm of choice is similar to greedy meshing, although it doesn't merge quads so that they all become one quad. Here's what some of my important code looks like:
void build_mesh(chunk *c) {
if (c->meshes != NULL) {
vector_free(c->meshes); // deleted old mesh list
}
c->meshes = vector_create(); // creates a new mesh list
for (int x = 0; x < CHUNK_SIZE; x++) {
for (int y = 0; y < CHUNK_HEIGHT; y++) {
for (int z = 0; z < CHUNK_SIZE; z++) {
if (c->data[x][y][z] == 1) {
mesh m;
m.pos.x = x;
m.pos.y = y;
m.pos.z = z;
if (x - 1 < 0 || c->data[x - 1][y][z] == 0) {
// if we're in here that means we have to render the quad
m.type = X_MIN;
vector_add(&c->meshes, m);
}
if (x + 1 >= CHUNK_SIZE || c->data[x + 1][y][z] == 0) {
m.type = X_POS;
vector_add(&c->meshes, m);
}
if (y - 1 < 0 || c->data[x][y - 1][z] == 0) {
m.type = Y_MIN;
vector_add(&c->meshes, m);
}
if (y + 1 >= CHUNK_HEIGHT || c->data[x][y + 1][z] == 0) {
m.type = Y_POS;
vector_add(&c->meshes, m);
}
if (z - 1 < 0 || c->data[x][y][z - 1] == 0) {
m.type = Z_MIN;
vector_add(&c->meshes, m);
}
if (z + 1 >= CHUNK_SIZE || c->data[x][y][z + 1] == 0) {
m.type = Z_POS;
vector_add(&c->meshes, m);
}
}
}
}
}
}
void render_chunk(chunk *c, vert *verts, unsigned int program, mat4 model, unsigned int modelLoc, bool greedy) {
// meshing code
if (greedy) {
for (int i = 0; i < vector_size(c->meshes); i++) {
glm_translate_make(model, (vec3){c->meshes[i].pos.x, c->meshes[i].pos.y, c->meshes[i].pos.z});
setMat4(modelLoc, model);
glBindVertexArray(verts[c->meshes[i].type].VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
return;
}
for (int x = 0; x < CHUNK_SIZE; x++) {
for (int y = 0; y < CHUNK_HEIGHT; y++) {
for (int z = 0; z < CHUNK_SIZE; z++) {
for (int i = 0; i < 6; i++) {
if (c->data[x][y][z] == 1) {
glm_translate_make(model, (vec3){x, y, z});
setMat4(modelLoc, model);
glBindVertexArray(verts[i].VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
}
}
}
}
}
build_mesh only gets called when the chunk gets updated and render_chunk gets called every frame. If greedy is true, greedy meshing is implemented. However, the problem is that greedy meshing is significantly slower than just rendering everything, which should not be happening. Does anyone have any ideas what's going on?
Edit: After timing the mesh rendering, it take ~30-40 ms per frame. However, it scales up really well and still take 30-40 ms regardless of how large the chunk is.