我正在尝试在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;
}
虽然这有效,但在此循环中调用glUniformMatrix4fv
和glDrawArrays
似乎不是最好的主意。
在VBO
中发送“已转换”精灵坐标并从着色器中删除模型矩阵会不会更好?
如果是这样,怎么办呢?
或者我应该将所有模型矩阵连接成一个矩阵并使用它?
是否有更有效或标准的方式来做到这一点?
感谢。