Uniform Buffer
Uniform Buffer 是一个很有用的缓存,可以将大量的需要传递至多个着色器的矩阵、向量数据等存储在uniform buffer中。这是一个公共的缓存,所以当多个着色器需要传递相同的数据时,可以使用uniform buffer,减少代码量,应该也可以较少CUP传递至GPU的数据量。
大体思路是: 各个着色器中定义uniform块,在OpenGL中定义uniform缓冲,但是这样不知道哪个uniform缓冲 对应 哪个uniform块。为了解决这个问题,OpenGL上下文中设置有绑定点,故我们可以将uniform块绑定到一个bind point,然后将uniform缓冲绑定相同的bind point,这样就对应起来了。
1、着色器中定义uniform块,并设置绑定点
#version 430 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; out VS_OUT{ vec3 FragPos; vec3 Normal; }vs_out; layout (std140, binding=0) uniform Matrix{ mat4 projection; mat4 view; }; uniform mat4 model; void main() { vs_out.Normal = mat3(transpose(inverse(model))) * aNormal; vs_out.FragPos = vec3(model * vec4(aPos,1.0f)); gl_Position = projection * view * vec4(vs_out.FragPos, 1.0); }
上面的红色代码就是uniform块。
binding=0就是设置uniform块 Matrix 的绑定点为0,这样直接在 shader 中设置绑定点必须在GLSL 4.2以上版本中使用。当然也可以直接在OpenGL中设置绑定点:(不受GLSL版本限制)
unsigned int matrix_index = glGetUniformBlockIndex(shader.ID, "Matrix"); glUniformBlockBinding(shader.ID, matrix_index, 0);
2、定义Uniform Buffer,设置绑定点
void Cube::setupUniformBuffer() { glGenBuffers(1, &this->ubo); glBindBuffer(GL_UNIFORM_BUFFER, this->ubo); glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), NULL, GL_STATIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBufferBase(GL_UNIFORM_BUFFER, 0, this->ubo); }
glBufferData()是用来分配内存的。
3、更新uniform buffer
void Cube::setViewMat(glm::mat4 view) { glBindBuffer(GL_UNIFORM_BUFFER, this->ubo); glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(view)); glBindBuffer(GL_UNIFORM_BUFFER, 0); }
效果图如下:
使用四个shader,用四种不同的颜色渲染四个盒子