使用OpenGL在2D中绘制多个对象

时间:2018-03-04 15:06:42

标签: opengl

我正在尝试在OpenGL中渲染多个精灵,并希望获得一些有关效率的建议。我也可能错过了一个关键概念。

在我的示例中,我使用orthographic投影将视口坐标转换为规范化设备坐标。

每个精灵也会有一个model矩阵。

顶点着色器包含以下代码:

#version 410

layout (location=0) in vec2 a_position;

uniform mat4 u_model;
uniform mat4 u_projection;

void main() {
  vec4 pos = vec4(a_position.x, a_position.y, 0.0, 1.0);
  gl_Position = u_projection * u_model * pos;
}

片段着色器非常简单:

#version 410

out vec4 frag_color;

void main() {
  frag_color = vec4(1.0, 1.0, 1.0, 1.0);
}

使用GLFW创建窗口并初始化GL上下文后, 我从着色器中检索attributes

GLuint u_model = glGetUniformLocation(prog, "u_model");
GLuint u_projection = glGetUniformLocation(prog, "u_projection");

我创建了一个VAO和一个VBO,其中包含三角形顶点

这就是我认为我错了的地方)

GLfloat vertices[6] = {
     0.0, -1.0,
    -1.0,  1.0,
     1.0,  1.0
};

GLuint vao;
GLuint vbo;

glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), 
    vertices, GL_STATIC_DRAW);

glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, 
    GL_FALSE, 
    2 * sizeof(GLfloat), (GLvoid*) 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

我还设置了正交投影:

glm::mat4 projection = glm::ortho(0.0f,
        (float) viewport_width, (float) viewport_height,
        0.0f, -1.0f, 0.0f);

glUniformMatrix4fv(u_projection, 1, 
    GL_FALSE, (const float*) glm::value_ptr(projection));

然后我实例化了一些 sprites

const int MAX_SPRITES = 10;
struct sprite {
  float rotation;
  glm::vec2 position;
  glm::vec2 size;
};
sprite sprites[MAX_SPRITES];

for (int i = 0; i < MAX_SPRITES; i++) {
    float x = 20.0f + (i * 50.0f);
    float y = (float) viewport_height * 0.5;

    sprites[i].position = glm::vec2(x, y);
    sprites[i].rotation = 0.0f;
    sprites[i].size = 20.0f;
}

然后在渲染循环中,我更新精灵rotation并绘制它们

for (int i = 0; i < MAX_SPRITES; i++) {
    sprites[i].rotation += elapsed_seconds;

    glm::mat4 model = draw_sprite( 
        sprites[i].position, sprites[i].size, 
        sprites[i].rotation);

    glUniformMatrix4fv(u_model, 
        1, GL_FALSE, 
        (const float*) glm::value_ptr(model));

    glBindVertexArray(vao);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0);
}

函数draw_sprite的定义如下:

glm::mat4 draw_sprite
(glm::vec2 position, glm::vec2 size, GLfloat rotate) {
    glm::mat4 model;
    model = glm::translate(model, glm::vec3(position, 1.0f));

    model = glm::translate(model, glm::vec3(
        0.5 * size.x, 0.5f * size.y, 0.0));
    model = glm::rotate(model, rotate, glm::vec3(0.0f, 0.0f, 1.0f));
    model = glm::translate(model, glm::vec3(
        -0.5 * size.x, -0.5f * size.y, 0.0));

    model = glm::scale(model, glm::vec3(size, 1.0f));
    return model;
}

虽然这有效,但在此循环中调用glUniformMatrix4fvglDrawArrays似乎不是最好的主意。

VBO中发送“已转换”精灵坐标并从着色器中删除模型矩阵会不会更好? 如果是这样,怎么办呢? 或者我应该将所有模型矩阵连接成一个矩阵并使用它?

是否有更有效或标准的方式来做到这一点?

感谢。

0 个答案:

没有答案