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,用四种不同的颜色渲染四个盒子

 

posted @ 2019-09-02 16:28 茶飘香~ 阅读(...) 评论(...) 编辑 收藏