构建Uniform blocks, 将此结构数据存入 buffer object, 性能会有很大的提高。
这篇对uniform buffer object 的std140规则, uniform block赋值讲解的非常详细
https://learnopengl.com/#!Advanced-OpenGL/Advanced-GLSL
记录下书中的例子。以下是vertextShader:
#version 440 core
in vec4 position;
out VS_OUT
{
vec4 color;
} vs_out;
// default block uniform
uniform mat4 mv_matrix;
// uniform block
//推荐的memory layout qualifier是 std140
//binding point 连接uniform block 与 buffer object
layout(std140, binding = 0) uniform TransformBlock
{
mat4 proj_matrix;
};
void main()
{
// mvp 变换
gl_Position = proj_matrix * mv_matrix * position;
vs_out.color = position * 2.0 + vec4(0.5, 0.5, 0.5, 0.0);
}
以下是Start()内:
// cube
static const GLfloat vertex_positions[] =
{
-0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, 0.5f
};
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// vertex attribute
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_positions), vertex_positions, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
program = getProgram("vertexshader.glsl", "fragmentshader.glsl");
// projection matrix
proj_matrix = glm::perspective(50.0f, ((float)screenWidth ) / (screenHeight), 0.1f, 1000.0f);
GLuint uboBuffer;
glGenBuffers(1, &uboBuffer);
glBindBuffer(GL_UNIFORM_BUFFER, uboBuffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), glm::value_ptr(proj_matrix), GL_STATIC_DRAW);
//将buffer object 绑定到 索引缓冲区目标,即顶点着色器内binding的值
glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBuffer);
glBindVertexArray(0);
以下是Render()内:
GLfloat currentTime = glfwGetTime();
deltaTime = currentTime - lastFrame;
lastFrame = currentTime;
GLfloat colors[] = {.3, 0.3, .3, 1.0};
glClearBufferfv(GL_COLOR, 0, colors);
glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0);
glBindVertexArray(vao);
for (size_t i = 0; i < 24; i++)
{
glUseProgram(program);
float f = (float)i + currentTime * 0.3f;
// viewMatrix * rotate * translate
mv_matrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f)) *
glm::rotate(glm::mat4(1.0f), 45.0f, glm::vec3(0.0f, 1.0f, 0.0f)) *
glm::translate( glm::mat4(1.0f), glm::vec3(sinf(2.1f * f) * 2.0f,cosf(1.7f * f) * 2.0f,sinf(1.3f * f) * cosf(1.5f * f) * 2.0f)) *
camera.GetViewMatrix();
// default block uniform 获取 location 后直接赋值
glUniformMatrix4fv(glGetUniformLocation(program, "mv_matrix"), 1, GL_FALSE, glm::value_ptr(mv_matrix));
glDrawArrays(GL_TRIANGLES, 0, 36);
// 线框型cube
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
glBindVertexArray(0);
//glViewport(0, 0, screenWidth / 2.0f, screenHeight / 2.0f);