Рисование чанка с помощью OpenGL - PullRequest
0 голосов
/ 19 мая 2018

У меня есть некоторые проблемы с моими шейдерами / vbo / vao с OpenGL.

Ситуация

Я создал геометрический шейдер , который позволяет мне рисовать кубиз положения (Положение устанавливается с использованием униформы).

Я пытаюсь использовать систему чанков до , чтобы уменьшить количество вызовов отрисовки .Проблема в том, что я не могу найти способ начать.Как уменьшить количество вызовов отрисовки, но при этом отрисовывать как можно больше кубов?

Идеи реализации

Я думал о переработке своего геометрического шейдера с помощью 3 циклов for из 16 итераций, чтобы сгенерировать позиции вершин моего4096 кубов.Другой возможностью, которую я имел в виду, было вызывать 4096 раз мой шейдер для каждой позиции.(Я новичок в OpenGL, но я не уверен, что это возможно).

Мои трудности

  • Должен ли я отправлять эти позиции (или указатели в моем чанке, что я 'Будем ли преобразовывать в позицию) в мой шейдер с одинарным или VBO?
  • В случае VBO, можно ли отправить массив uint8_t?Каждый элемент массива будет содержать байт, чтобы указать тип блока, 0 для воздуха, 1 для грязи.Обратите внимание, что индексы массива будут использоваться для определения позиции блока.( Например: chunk_data[0][5][2] позиция будет vec3(0.f, 5.f, 2.f) + chunk_position, а его тип - грязь ).
  • Опять же, если я выберу VBO, можно ли изменить: layout (location = 0) in vec3 position; в массив байтов (int, я думаю, потому что GLSL не предоставляет байтов / uint8_t)

Edit

Я нашел, благодаря @Acorn, что рисование экземпляров может помочь мнеулучшить мои выступления.Сейчас я пытаюсь понять, как на самом деле работает рисование экземпляров и как применить это к моей проблеме.Пока я думаю, что мне нужно определить, что будет содержать мой экземплярный массив (я думаю, это будут позиции и типы блоков)

Ресурсы

RenderingManager.cpp (Метод, который обрабатывает воксельрисование)

void ElkRendering::Managers::RenderingManager::DrawVoxel(const glm::vec3 & p_position)
{
    if (m_currentTexture && m_currentShader)
    {
        m_currentShader->SetUniformVec3("u_position", p_position);
        m_voxel.Draw(*m_currentShader);
    }
}

Voxel.cpp (методы настройки и рисования)

void Voxel::Setup()
{
    GLfloat verts[] =
    {
        0.0f, 0.0f, 0.0f
    };

    glGenVertexArrays(1, &m_vao);
    glGenBuffers(1, &m_vbo);

    glBindVertexArray(m_vao);

    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glBindVertexArray(0);
}

void Voxel::Draw(Shader& p_shader)
{
    PROFILER_SPY("Voxel::Draw");

    glBindVertexArray(m_vao);
    glDrawArrays(GL_POINTS, 0, 1);
    glBindVertexArray(0);
}

Chunk.cpp (просто идея, этокод не работает вообще и не завершен)

void Chunk::Setup()
{
    for (uint8_t x = 0; x < 16; ++x)
    {
        for (uint8_t y = 0; y < 16; ++y)
        {
            for (uint8_t z = 0; z < 16; ++z)
            {
                blocks[x][y][z] = 1;
            }
        }
    }

    glGenVertexArrays(1, &m_vao);
    glGenBuffers(1, &m_vbo);

    glBindVertexArray(m_vao);

    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(uint8_t) * 16 * 16 * 16, blocks, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glBindVertexArray(0);
}

void Chunk::Draw(Shader& p_shader)
{
    glBindVertexArray(m_vao);
    glDrawArrays(GL_POINTS, 0, 1);
    glBindVertexArray(0);
}

voxel.glsl

#shader vertex
#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texCoord;

out vec3 v_pos;

void main()
{
    v_pos = position;
}

#shader geometry
#version 330 core

layout (points) in;
layout (triangle_strip, max_vertices = 24) out;

uniform vec3 u_position;
uniform mat4 u_vp;

const float textCount = 3.0f;

const vec3 cubeVertex[8] = vec3[8]
(
    /* Z+ (Front) */
    vec3(-0.5f, -0.5f, +0.5f),  // 0
    vec3(-0.5f, +0.5f, +0.5f),  // 1
    vec3(+0.5f, -0.5f, +0.5f),  // 2
    vec3(+0.5f, +0.5f, +0.5f),  // 3

    /* Z- (Back) */
    vec3(-0.5f, -0.5f, -0.5f),  // 4
    vec3(-0.5f, +0.5f, -0.5f),  // 5
    vec3(+0.5f, -0.5f, -0.5f),  // 6
    vec3(+0.5f, +0.5f, -0.5f)   // 7
);

const int  cubeIndices[24]  = int[24]
    (
        1,0,3,2,  // Z+ (Front)
        3,2,7,6,  // X+ (Right)
        7,6,5,4,  // Z- (Back)
        5,4,1,0,  // X- (Left)
        0,4,2,6,  // Y- (Bottom)
        5,1,7,3   // Y+ (Top)
    );

const vec2 textCoords[24] = vec2[24]
(
    vec2(1/textCount, 1),  vec2(1/textCount, 0), vec2(2/textCount, 1), vec2(2/textCount, 0), // Front
    vec2(1/textCount, 1),  vec2(1/textCount, 0), vec2(2/textCount, 1), vec2(2/textCount, 0), // Right
    vec2(1/textCount, 1),  vec2(1/textCount, 0), vec2(2/textCount, 1), vec2(2/textCount, 0), // Back
    vec2(1/textCount, 1),  vec2(1/textCount, 0), vec2(2/textCount, 1), vec2(2/textCount, 0), // Left
    vec2(2/textCount, 1),  vec2(2/textCount, 0), vec2(1, 1), vec2(1, 0), // Bottom
    vec2(0, 1),  vec2(0, 0), vec2(1/textCount, 1), vec2(1/textCount, 0) // Top
);

out vec2 textureCoord;
out float lighting;

void main() 
{
    mat4 model = mat4(1.0, 0.0, 0.0, 0.0,  0.0, 1.0, 0.0, 0.0,  0.0, 0.0, 1.0, 0.0,  u_position.x, u_position.y, u_position.z, 1.0);
    mat4 mvp = u_vp * model;

    for (int i = 0; i < 24; ++i) 
    {
        gl_Position = mvp * (gl_in[0].gl_Position + vec4(cubeVertex[cubeIndices[i]], 0));
        textureCoord = textCoords[i];

        if (i >= 16 && i < 20)
            lighting = 0.2f;
        else if (i >= 20)
            lighting = 1.0f;
        else
            lighting = 0.6f;

        EmitVertex();
        if ((i + 1) % 4 == 0) EndPrimitive();
    }
}

#shader fragment
#version 330 core

uniform sampler2D tex;

out vec4 FragColor;

in vec2 textureCoord;
in float lighting;

void main()
{
    // Final color
    FragColor = texture2D(tex, textureCoord) * lighting;
}
...