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,用四種不同的顏色渲染四個盒子