[OpenGL 超级宝典][笔记] 8.1 PBO介绍与用法
来源:互联网 发布:数据库设置主键的语句 编辑:程序博客网 时间:2024/06/01 09:11
像素缓冲区对象(PixelBufferObject)
在上一节中,我们介绍了通用的缓冲区的创建,使用,删除。
当通用的缓冲区对象绑定到PBO缓冲点时,一个缓冲区才成为一个像素缓冲区。
优点:
- PBO存放数据时,需要先通过glBufferData 申请GPU内存。
- 操作都是在GPU管线中进行,不需要等待所有的活动停止后,就可以将新数据发送到GPU中。提高性能。
Example1:
ReadPixels 将数据从GPU拷贝到CPU端内存块data
// Code 1void* data = (void*)malloc(pixelDataSize);glReadBuffer(GL_BACK_LEFT);glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGB,GL_UNSIGNED_BYTE, NULL);
使用了GL_PIXEL_PACK_BUFFER绑定点后,ReadPixels 将数据从GPU拷贝到GPU端的名为pixBufferObjs[0]的Buffer
// Code2glReadBuffer(GL_BACK_LEFT);glBindBuffer(GL_PIXEL_PACK_BUFFER, pixBufferObjs[0]);glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGB,GL_UNSIGNED_BYTE, NULL);
Code2相对Code1, 对于需要将绘制结果回拷到GPU的应用场景,会有极大的性能提升,并且代码简单。
Example2:
运动模糊 (Motion Blur) 效果有助于显示场景中哪些对象是运动的,以及它们运动有多快。
程序中的一种简单的处理方式是:将绘制出的前端的几帧结果存储并与当前帧混合到一起。
下面的示例中,采用二种方式,分别实现Motion Blur的效果:一种是将GPU绘制的数据拷贝到CPU中,再拷贝到GPU中进行运动模糊。另一种是直接使用PBO的方式,如示例代码Code2中,直接将GPU绘制的结果,拷贝到GPU的PBO中,进行运动模糊。
示例代码如下:
纹理与PBO的初始化
glGenTextures(6, blurTextures); // Create Textures// 分配像素缓冲区来对纹理和PBO初始化pixelDataSize = GetWidth() * GetHeight() * 3 * sizeof(unsigned byte);void* data = (void*)malloc(pixelDataSize);memset(data, 0x00, pixelDataSize);// 设置纹理单元并初始化纹理数据for(int i=0; i<6; i++){ glActiveTexture(GL_TEXTURE1 + i); glBindTexture(GL_TEXTURE_2D, blurTextures[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GetWidth(), GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, data);}// 为像素的复制分配空间,避免每次进行绘制时都调用函数原形glGenBuffers(1, pixBuffObjects);glBindBuffer(GL_PIXEL_PACK_BUFFER, pixBuffObjs[0]);glBufferData(GL_PIXEL_PACK_BUFFER, pixelDataSize, pixelData, GL_DYNAMIC_COPY);glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
将绘制结果作为纹理,通常有二种方式,如下:
- 传统的方式,是使用glReadPixels来得到像素数据,调用glTexImage2D将像素数据复制GPU的纹理对象上去。
- 使用PBO的方式时,绑定到GL_PIXEL_PACK_BUFFER, 调用glReadPixels时,这些像素将重新定向到PBO而不是再次回到CPU。解除绑定后,绑定到GL_PIXEL_UNPACK_BUFFER, 调用glTexImage2D时,缓冲区中的数据将加载到纹理上。
if(bUsePBOPatch){ //绑定到包装绑定点,然后将像素读取到PBO中 glBindBuffer(GL_PIXEL_PACK_BUFFER, pixBuffObjs[0]); glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, NULL); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); // 绑定到解包绑定点上,然后将像素读取到PBO中,再将像素放入纹理 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixBuffObjs[0]); // 为新模糊设置纹理,每一帧都有增加 glActiveTexture(GL_TEXTURE0 + GetBlurTarget0()); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, GetWidth(), GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);}else{ // 获取屏幕像素并复制客户端内存 glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, pixelData); //将像素从客户端内存中移到纹理中 //为新的模糊设置纹理单元,每一帧都增加 glActiveTexture( GL_TEXTURE0 + GetBlurTarget0() ); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, GetWidth(), GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, pixelData);}
Shader 片段着色器
#version 150in vec2 vTexCoord;uniform sampler2D textureUnit0;uniform sampler2D textureUnit1;uniform sampler2D textureUnit2;uniform sampler2D textureUnit3;uniform sampler2D textureUnit4;uniform sampler2D textureUnit5;void main(void){ vec4 blur0 = texture(textureUnit0, vTexCoord); vec4 blur1 = texture(textureUnit1, vTexCoord); vec4 blur2 = texture(textureUnit2, vTexCoord); vec4 blur3 = texture(textureUnit3, vTexCoord); vec4 blur4 = texture(textureUnit4, vTexCoord); vec4 blur5 = texture(textureUnit5, vTexCoord); vec4 summedBlur = blur0 + blur1 + blur2 + blur3 + blur4 + blur5; gl_FragColor = summedBlur / 6.0;}
结论:
PBO的方式,比传统的方式性能上快很多。
- [OpenGL 超级宝典][笔记] 8.1 PBO介绍与用法
- [openGL超级宝典][笔记][8.1缓冲区]
- 《OpenGL超级宝典》笔记(一)
- OpenGL超级宝典笔记(三)
- OpenGL超级宝典笔记4
- OpenGL超级宝典笔记5
- OpenGL超级宝典笔记6
- OpenGL超级宝典笔记7
- OpenGL超级宝典笔记8
- OpenGL超级宝典笔记——镜面光与法线平均
- 《OpenGL 超级宝典(Super Bible)第五版》 有关 PBO 的 Example
- [OpenGL 超级宝典][笔记] 8.1 纹理缓冲区(TBO)
- OpenGL超级宝典学习笔记前言
- OpenGL 3D 超级宝典学习笔记
- OpenGL超级宝典笔记(二)
- OpenGL超级宝典笔记9(完)
- OpenGL超级宝典笔记一 - 基础渲染
- OpenGL超级宝典笔记二 - 基础变换
- CountDownLatch
- 微服务,微架构[十一]springboot模板页面thymeleaf
- java构造函数详解
- 读文献笔记:汇率政策新共识与“”中间制度消亡论“”
- Nested Segments CodeForces 652D 树状数组+离散化
- [OpenGL 超级宝典][笔记] 8.1 PBO介绍与用法
- 内省操作javabean
- Java中String对象创建机制详解
- 基于Scrapy分布式爬虫的开发与设计
- [BZOJ]1192: [HNOI2006]鬼谷子的钱袋
- 2017年上海金马五校程序设计竞赛(网上资格赛)Problem H : DHU Club Festival
- lintcode:跳跃游戏——解析
- 51Nod-1799-二分答案
- 设计模式之策略模式