用OpenGL绘制一个块

时间:2018-05-19 02:33:26

标签: c++ opengl glsl vbo

我的shader / vbo / vao使用OpenGL时遇到了一些麻烦。

情况

我创建了一个几何着色器,它允许我从一个位置绘制一个立方体(使用制服设置的位置)。

我尝试使用块系统减少我的绘制调用。问题是我无法找到开始的方法。如何减少绘制调用但仍然渲染多个立方体?

实施思路

我正在考虑使用3次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)

修改

我发现,感谢@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;
}

0 个答案:

没有答案