我在使用 OpenGL 的着色器/vbo/vao 方面遇到了一些问题。
情况
我创建了一个几何着色器,它允许我从一个位置(使用制服的位置集)绘制一个立方体。
我正在尝试使用块系统来减少我的绘图调用。问题是我找不到开始的方法。如何减少绘图调用但仍渲染尽可能多的立方体?
实施思路
我正在考虑使用 3 个 16 次迭代的 for 循环来重新设计我的几何着色器,以生成 4096 个立方体的顶点位置。我想到的另一种可能性是为每个位置调用 4096 次我的着色器。(我是 OpenGL 的初学者,但我不确定这是否可行)。
我的困难
- 我应该使用 uniform 还是 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)
编辑
我发现,感谢@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);
}
体素.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;
}