缓冲区
特性:缓冲区存储在GPU显存中,可提供高速高效的访问显存的方式。
作用:
- 可以将数据从一个渲染管线移动到另一个渲染管线(GPU显存中).
- 可以从一个对象绑定到另一个对象.
- 可以将GPU中数据移动到合适位置,不需CPU介入。如PBO移动数据到Texture中
缓冲区使用:
缓冲区的创建,Binding, 删除的示例代码如下:
// Step1: 为新缓冲区创建名称
gluint pixBufObject[1];
glGenBuffer(1, pixBufObject);
// Step2: 根据不同的绑定点也就是目的,使用缓冲区
// 下例中,是以像素包装缓冲区绑定点,使用GLReadPixels将像素数据复制到缓冲区中。
glBindBuffer(GL_PIXEL_PACK_BUFFER, pixBufObject[0]);
//Step3:对一个缓冲区解除绑定,则可调用以0为缓冲区名称
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
//Step4: 用完缓冲区后,清除缓冲区, 则DeleteBuffers + 缓冲区名
glDeleteBuffers(1, pixBufObject);
绑定点
缓冲区可以先分配,再设置绑定点。绑定点的不同,作用也不同。OpenGL通常有如下的绑定点。
绑定点 | 作用 |
---|---|
GL_ARRAY_BUFFER | 数据缓冲区存储颜色,位置,纹理坐标或其它自定义属性 |
GL_COPY_READ_BUFFER | 指定 glCopyBufferSubData 复制的数据源 |
GL_COPY_WRITE_BUFFER | 指定 glCopyBufferSubData 要复制到的地方(目标) |
GL_ELEMENT_ARRAY_BUFFER | 索引数据缓冲区用于保存glDrawElements, glDrawRangeElements, glDrawElementsInstanced 的索引。 |
GL_PIXEL_PACK_BUFFER | 指定glReadPixels等将像素拷贝到的目标地方。 |
GL_PIXEL_UNPACK_BUFFER | glTexImage**, glTexSubImage**,等纹理更新函数的源缓冲区 |
GL_TEXTURE_BUFFER | 通过纹理单元拾取来访问的缓冲区。 |
GL_TRANSFORM_FEEDBACK_BUFFER | 变换反馈顶点着色器写入的缓冲区 |
GL_UNIFORM_BUFFER | 着色器能访问的Uniform值 |
上面的各个绑定点,代表不同的Buffer的用法。如PBO常绑定GL_PIXEL_PACK_BUFFER,TBO指绑定GL_TEXTURE_BUFFER,UBO指绑定GL_UNIFORM_BUFFER,VAO中常使用GL_ARRAY_BUFFER等。后续的很多缓冲区的用法,都是根据绑定点不同来使用的。
缓冲区的填充
填充缓冲区,也就是将数据传递到缓冲区中。通常是从CPU拷贝内存到GPU端。
- 方法1:使用glBufferData,如下例子:
glBindBuffer(GL_PIXEL_PACK_BUFFER, pixBufObject[0]);
// 参数1 GL_PIXEL_PACK_BUFFER,需与BindPoint 一致
// 参数2 数据大小,以字节Byte为单位。
// 参数3:pixelData 将要被上传的数据本身。当为Null时,表示申请特定大小的缓冲区,而不是立即上传数据。
// 参数4 告诉GL如何使用缓冲区。GL_DYNAMIC_COPY表示应用程序经常更新
glBufferData(GL_PIXEL_PACK_BUFFER, pixelDataSize, pixelData, GL_DYNAMIC_COPY);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
- 方法2:使用glBufferSubData(GLenum target, intptr offset, sizeiptr size, const void *data);更新缓冲区中的部分数据。有点类似于改变CPU端的部分数据。
总结:
缓冲区结束了传统很多操作需要GPU到CPU,CPU到GPU的效率低下的方式,带来OpenGL极大的提升。