How to create a Minecraft chunk in opengl?

Viewed 824

I'm learning OpenGL and I have tried to make a voxel game like Minecraft. In the beginning, everything was good. I created a CubeRenderer class to render a cube with its position. The below picture is what I have done.

https://imgur.com/yqn783x

And then I got a serious problem when I try to create a large terrain, I hit a slowing performance. It was very slow and fps just around 15fps, I thought. Next, I figured out Minecraft chunk and culling face algorithm can solve slowing performance by dividing the world map into small pieces like chunk and just rendering visible faces of a cube. So how to create a chunk in the right way and how the culling face algorithm is applied in Chunk?

So far, that is what I have tried I read about Chunk in Minecraft at https://minecraft.gamepedia.com/Chunk

I created a demo Chunk by this below code (it is not the completed code because I removed it out)

I created a CubeData that contains cube position and cube type. And I call the GenerateTerrain function to make a simple chunk data (16x16x16) like below (CHUNK_SIZE is 16)

for (int x = 0; x < CHUNK_SIZE; x++) {  
        for (int y = 0; y < CHUNK_SIZE; y++) {  
            for (int z = 0; z < CHUNK_SIZE; z++) {
                CubeType cubeType = { GRASS_BLOCK }; 
                Location cubeLocation = { x, y, z };
                CubeData cubeData = { cubeLocation, cubeType };
                this->Cubes[x][y][z] = cubeData;
            }
        }
    }

After that, I had a boolean array which is called "mask" contains two values are 0 (not visible) or 1 (visible) and matches with their cube data. And then I call Render function of Chunk class to render a chunk. This code below like what I have done (but it is not complete code because I removed that code and replaced with new code)

for (int x = 0; x < CHUNK_SIZE; x++) {  
        for (int y = 0; y < CHUNK_SIZE; y++) {  
            for (int z = 0; z < CHUNK_SIZE; z++) {
                for(int side = 0; side < 6;side++){
if(this->mask[x][y][z][side] == true) cubeRenderer.Render(cubeData[x][y][z]);
}
            }
        }
    }

But the result I got that everything still slow (but it is better than the first fps, from 15fps up to 25-30fps, maybe)

I guess it is not gpu problem, it is a cpu problem because there is too many loops in render call.

So I have kept research because I think my approach was wrong. There may have some right way to create a chunk, right?

So I found the solution that puts every visible verticle to one VBO. So I just have to call and bind VBO definitely one time.

So this below code show what I have tried

cout << "Generating Terrain..." << endl;

    for (int side = 0; side < 6; side++) {
        for (int x = 0; x < CHUNK_SIZE; x++) {
            for (int y = 0; y < CHUNK_SIZE; y++) {
                for (int z = 0; z < CHUNK_SIZE; z++) {
                    if (this->isVisibleSide(x, y, z, side) == true) {
                        this->cubeRenderer.AddVerticleToVBO(this->getCubeSide(side), glm::vec3(x, y, z), this->getTexCoord(this->Cubes[x][y][z].cubeType, side));
                    }
                }
            }
        }
    }

    this->cubeRenderer.GenerateVBO();

And call render one time at all.

void CubeChunk::Update()
{
    this->cubeRenderer.Render(); // with VBO data have already init above
}

And I got this:

https://imgur.com/YqsrtPP

I think my way was wrong.

So what should I do to create a chunk? Any suggestion?

0 Answers
Related