У меня есть некоторые проблемы с моими шейдерами / 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;
}