Я изучаю OpenGL и пытался создать воксельную игру, такую как Minecraft. В начале все было хорошо. Я создал класс CubeRenderer для рендеринга куба с его позицией. На рисунке ниже показано, что я сделал.
https://imgur.com/yqn783x
А потом у меня возникла серьезная проблема, когда я пытался создать большую местность, я столкнулся с замедленной производительностью. Я думал, что скорость была очень медленной, а частота кадров около 15 кадров в секунду. Затем я выяснил, что алгоритм Minecraft chunk и culling face может решить проблему снижения производительности, разделив карту мира на маленькие кусочки, такие как chunk, и просто визуализируя видимые грани куба. Итак, как правильно создать чанк и как применить алгоритм отбраковки граней в чанке?
До сих пор это то, что я пытался прочитать о чанке в Minecraft на https://minecraft.gamepedia.com/Chunk
*. 1010 * Я создал демонстрационный Chunk с помощью этого кода ниже (это не законченный код, потому что я его удалил)
Я создал CubeData, который содержит позицию и тип куба. И я вызываю функцию GenerateTerrain для создания простых данных чанка (16x16x16), как показано ниже (CHUNK_SIZE равно 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;
}
}
}
После этого у меня был логический массив, который называется «маска», содержит два значения: 0(не виден) или 1 (виден) и соответствует их данным куба. И тогда я вызываю функцию Render класса Chunk для рендеринга чанка. Этот код ниже похож на то, что я сделал (но это не полный код, потому что я удалил этот код и заменил его новым кодом)
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]);
}
}
}
}
Но в результате я получил, что все по-прежнему медленно (но это лучше, чемпервые fps, от 15fps до 25-30fps, может быть)
Я думаю, это не проблема с GPU, это проблема с процессором, потому что в вызове рендеринга слишком много циклов.
Я продолжал исследования, потому что я думаю, что мой подход был неправильным. Там может быть какой-то правильный способ создания чанка, верно?
Так что я нашел решение, которое помещает каждую видимую вертикалку в один VBO. Поэтому мне просто нужно определенно позвонить и связать VBO один раз.
Итак, этот код ниже показывает, что я пробовал
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();
И вызвать рендер один раз.
void CubeChunk::Update()
{
this->cubeRenderer.Render(); // with VBO data have already init above
}
И я получил это:
https://imgur.com/YqsrtPP
Я думаю, что мой путь был неправильным.
Так, что я должен сделать, чтобы создать чанк? Любое предложение?