Como escrever melhor um mecanismo voxel em C com o desempenho em mente [fechado]

Sou uma armadura no OpenGl e, por esse motivo, estou procurando aprender apenas o OpenGl moderno o material 4.x. Depois de concluir os tutoriais básicos (cubos rotativos, por exemplo). Decidi que tentaria criar um programa baseado em voxel que lida apenas com cubos. Os objetivos deste programa eram ser rápidos, usar energia e memória limitadas da CPU e ser dinâmicos, para que o tamanho do mapa pudesse mudar e os blocos só fossem desenhados se, na matriz, diz que o bloco estava cheio.

Eu tenho um VBO com os vértices e índices de um cubo construído a partir de triângulos. No começo, se a função render, eu digo ao OpenGl os shaders para usar e depois vinculo o VBO assim que estiver concluído, eu executo esse loop

Desenhar loop de cubo:

//The letter_max are the dimensions of the matrix created to store the voxel status in
// The method I use for getting and setting entries in the map are very efficient so I have not included it in this example
for(int z = -(z_max / 2); z < z_max - (z_max / 2); z++)
{
    for(int y = -(y_max / 2); y < y_max - (y_max / 2); y++)
    {
        for(int x = -(x_max / 2); x < x_max - (x_max / 2); x++)
        {
            DrawCube(x, y, z);
        }
    }
} 

Cube.c

#include "include/Project.h"

void CreateCube()
{
    const Vertex VERTICES[8] =
    {
    { { -.5f, -.5f,  .5f, 1 }, { 0, 0, 1, 1 } },
    { { -.5f,  .5f,  .5f, 1 }, { 1, 0, 0, 1 } },
    { {  .5f,  .5f,  .5f, 1 }, { 0, 1, 0, 1 } },
    { {  .5f, -.5f,  .5f, 1 }, { 1, 1, 0, 1 } },
    { { -.5f, -.5f, -.5f, 1 }, { 1, 1, 1, 1 } },
    { { -.5f,  .5f, -.5f, 1 }, { 1, 0, 0, 1 } },
    { {  .5f,  .5f, -.5f, 1 }, { 1, 0, 1, 1 } },
    { {  .5f, -.5f, -.5f, 1 }, { 0, 0, 1, 1 } }
    };

    const GLuint INDICES[36] =
    {
    0,2,1,  0,3,2,
    4,3,0,  4,7,3,
    4,1,5,  4,0,1,
    3,6,2,  3,7,6,
    1,6,5,  1,2,6,
    7,5,6,  7,4,5
    };

    ShaderIds[0] = glCreateProgram();
    ExitOnGLError("ERROR: Could not create the shader program");
    {
    ShaderIds[1] = LoadShader("FragmentShader.glsl", GL_FRAGMENT_SHADER);
    ShaderIds[2] = LoadShader("VertexShader.glsl", GL_VERTEX_SHADER);
    glAttachShader(ShaderIds[0], ShaderIds[1]);
    glAttachShader(ShaderIds[0], ShaderIds[2]);
    }
    glLinkProgram(ShaderIds[0]);
    ExitOnGLError("ERROR: Could not link the shader program");

    ModelMatrixUniformLocation = glGetUniformLocation(ShaderIds[0], "ModelMatrix");
    ViewMatrixUniformLocation = glGetUniformLocation(ShaderIds[0], "ViewMatrix");
    ProjectionMatrixUniformLocation = glGetUniformLocation(ShaderIds[0], "ProjectionMatrix");
    ExitOnGLError("ERROR: Could not get shader uniform locations");

    glGenVertexArrays(1, &BufferIds[0]);
    ExitOnGLError("ERROR: Could not generate the VAO");
    glBindVertexArray(BufferIds[0]);
    ExitOnGLError("ERROR: Could not bind the VAO");

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    ExitOnGLError("ERROR: Could not enable vertex attributes");

    glGenBuffers(2, &BufferIds[1]);
    ExitOnGLError("ERROR: Could not generate the buffer objects");

    glBindBuffer(GL_ARRAY_BUFFER, BufferIds[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VERTICES), VERTICES, GL_STATIC_DRAW);
    ExitOnGLError("ERROR: Could not bind the VBO to the VAO");

    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(VERTICES[0]), (GLvoid*)0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VERTICES[0]), (GLvoid*)sizeof(VERTICES[0].Position));
    ExitOnGLError("ERROR: Could not set VAO attributes");

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, BufferIds[2]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(INDICES), INDICES, GL_STATIC_DRAW);
    ExitOnGLError("ERROR: Could not bind the IBO to the VAO");

    glBindVertexArray(0);
}

void DestroyCube()
{
    glDetachShader(ShaderIds[0], ShaderIds[1]);
    glDetachShader(ShaderIds[0], ShaderIds[2]);
    glDeleteShader(ShaderIds[1]);
    glDeleteShader(ShaderIds[2]);
    glDeleteProgram(ShaderIds[0]);
    ExitOnGLError("ERROR: Could not destroy the shaders");

    glDeleteBuffers(2, &BufferIds[1]);
    glDeleteVertexArrays(1, &BufferIds[0]);
    ExitOnGLError("ERROR: Could not destroy the buffer objects");
}

void DrawCube(float x, float y, float z)
{
    ModelMatrix = IDENTITY_MATRIX;

    TranslateMatrix(&ModelMatrix, x, y, z);
    TranslateMatrix(&ModelMatrix, MainCamera.x, MainCamera.y, MainCamera.z);

    glUniformMatrix4fv(ModelMatrixUniformLocation, 1, GL_FALSE, ModelMatrix.m);
    glUniformMatrix4fv(ViewMatrixUniformLocation, 1, GL_FALSE, ViewMatrix.m);
    ExitOnGLError("ERROR: Could not set the shader uniforms");


    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, (GLvoid*)0);
    ExitOnGLError("ERROR: Could not draw the cube");
}

O sombreador de vértice lida apenas com a rotação e transformação dos vértices e o sombreador de fragmento lida apenas com a cor que eles não são caros para executar, portanto não são o gargalo.

Como esse código pode ser aprimorado para renderizar com mais eficiência e aproveitar ao máximo os recursos modernos do OpenGL para diminuir a sobrecarga?

P.S. Não estou procurando um livro, uma ferramenta ou um recurso externo como resposta. Eu usei o backface culling e o teste de profundidade do OpenGL para tentar melhorar a velocidade, mas eles não fizeram uma diferença drástica, ainda está levando ~ 50ms para renderize um quadro e isso é demais para uma grade de voxel de 32 * 32 * 32.

Aqui está a captura de tela do que estou fazendo:

E aqui link para o código completo:

GitHUB Voxel Viewer

questionAnswers(2)

yourAnswerToTheQuestion