1.什么是PBO

OpenGL PBO(Pixel Buffer Object),被称为像素缓冲区对象,主要被用于异步像素传输操作。PBO 仅用于执行像素传输,不连接到纹理,且与 FBO (帧缓冲区对象)无关。

OpenGL PBO(像素缓冲区对象) 类似于 VBO(顶点缓冲区对象),PBO 开辟的也是 GPU 缓存,而存储的是图像数据。

PBO 绑定相关的 Target 标签有 2 个:

  • GL_PIXEL_UNPACK_BUFFER:将PBO绑定到这个上边,glTexImage2D和glTexSubImage2D() 表示从PBO中解包像素数据并恢复到帧缓冲区

  • GL_PIXEL_PACK_BUFFER:将PBO绑定到这个上边时,glReadPixels()表示从帧缓冲区中读取数据并打包进PBO

2.为什么要使用PBO

处理高分辨率的图像时,图像数据在内存和显存之前拷贝往往会造成性能瓶颈,而利用 PBO 可以在一定程度上解决这个问题。

使用 PBO 可以在 GPU 的缓存间快速传递像素数据,不影响 CPU 时钟周期,除此之外,PBO 还支持异步传输。

传统的方式:从文件中加载纹理,图像数据首先被加载到 CPU 内存中,然后通过 glTexImage2D 函数将图像数据从 CPU 内存复制到 OpenGL 纹理对象中 (GPU 内存),两次数据传输(加载和复制)完全由 CPU 执行和控制。

使用PBO的方式:可以通过 glMapBufferRange 获取 PBO 对应 GPU 缓冲区的内存地址。将图像数据加载到 PBO 后,再将图像数据从 PBO 传输到纹理对象中完全是由 GPU 控制,不会占用 CPU 时钟周期。所以,绑定 PBO 后,执行 glTexImage2D (将图像数据从 PBO 传输到纹理对象) 操作,CPU 无需等待,可以立即返回。

通过对比这两种(将图像数据传送到纹理对象中)方式,可以看出,利用 PBO 传输图像数据,省掉了一步 CPU 耗时操作(将图像数据从 CPU 内存复制到 纹理对象中)

3.PBO的使用

3.1PBO的创建
/*** 创建PBO 用于读取纹理上的像素数据* StreamRead 流的方式读取*/
m_PBOfst = new MSOpenGLBuffer(MSOpenGLBuffer::PixelPackBuffer,MSOpenGLBuffer::StreamRead);
m_PBOsnd = new MSOpenGLBuffer(MSOpenGLBuffer::PixelPackBuffer,MSOpenGLBuffer::StreamRead);
//构造函数
MSOpenGLBuffer::MSOpenGLBuffer(MSOpenGLBuffer::Type type, MSOpenGLBuffer::UsagePattern usage):m_bufferType(type),m_usage(usage),m_buffSize(0)
{glGenBuffers(1, &m_buffID);}

创建方式是GL_PIXEL_PACK_BUFFER,用于从纹理上读取像素数据,用于流的方式进行读取。

3.2PBO设置bufferData
m_PBOfst->Bind();
m_PBOfst->SetBufferData(nullptr,m_nResolution.x*m_nResolution.y*4);
m_PBOfst->Release();m_PBOsnd->Bind();
m_PBOsnd->SetBufferData(NULL,m_nResolution.x * m_nResolution.y * 4);
m_PBOsnd->Release();
//Bind 函数
void MSOpenGLBuffer::Bind()
{glBindBuffer(m_bufferType, m_buffID);
}
//release函数
void MSOpenGLBuffer::Release()
{glBindBuffer(m_bufferType, 0);
}void MSOpenGLBuffer::SetBufferData(const GLvoid *data, GLsizeiptr size)
{if (size > m_buffSize) {m_buffSize = size;glBufferData(m_bufferType, size, data, m_usage);} else {glBufferSubData(m_bufferType, 0, size, data);}
}

给连个PBO设置BufferData

3.3通过PBO进行数据读取
/*** 通过m_currIdx 来控制 两个PBO交替控制*/
void MSGLScene::processPBOReadPixels() {glReadBuffer(GL_FRONT);if(m_currIdx == 0){readPixelsFromPBO(m_PBOfst,m_PBOsnd);m_currIdx =1;}else{readPixelsFromPBO(m_PBOsnd,m_PBOfst);m_currIdx =0;}
}void MSGLScene::readPixelsFromPBO(MSOpenGLBuffer *fstBuff, MSOpenGLBuffer *sndBuff) {int w = m_nResolution.x;int h = m_nResolution.y;fstBuff->Bind();glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,0);//READsndBuff->Bind();void* data= glMapBufferRange(GL_PIXEL_PACK_BUFFER,0,w*h*4,GL_MAP_READ_BIT);if (data){MSVideoWriter::GetInstance()->WriteVideoFrameWithRgbData((const unsigned char*)data);}glUnmapBuffer(GL_PIXEL_PACK_BUFFER);glBindBuffer(GL_PIXEL_PACK_BUFFER,0);}

通过两个PBO交替读取数据,glMapBufferRange读取到结果就是:从纹理上读取到的RBG数据,此时数据就可以交给FFmpeg或者MediaCodec进行编码,并进行视频合成了。

Android OpenGL ES 3.0 PBO像素缓冲区对象相关推荐

  1. Android OpenGL ES 2.0 屏幕坐标和3D世界坐标转换

    Android OpenGL ES 2.0 屏幕坐标和3D世界坐标转换 查看全文 http://www.taodudu.cc/news/show-6705596.html 相关文章: word中如何加 ...

  2. Android opengl es 3.0 + ndk 绘画涂鸦项目

    前言 写一个opengl es 3.0 + ndk 的绘画涂鸦项目,命名为白板哈哈哈,记录自己遇到的问题,顺便学到的知识整合一遍,算是对自己一段时间的总结. 项目地址:Whiteboard 如果对你有 ...

  3. 使用Android OpenGL ES 2.0绘图之五:添加运动

    传送门☞Android兵器谱☞转载请注明☞http://blog.csdn.net/leverage_1229 传送门☞系统架构设计☞转载请注明☞http://blog.csdn.net/levera ...

  4. 使用Android OpenGL ES 2.0绘图之四:应用投影和相机视图

    传送门☞Android兵器谱☞转载请注明☞http://blog.csdn.net/leverage_1229 传送门☞系统架构设计☞转载请注明☞http://blog.csdn.net/levera ...

  5. 使用Android OpenGL ES 2.0绘图之一:搭建一个OpenGL ES环境

    传送门☞Android兵器谱☞转载请注明☞http://blog.csdn.net/leverage_1229 传送门☞系统架构设计☞转载请注明☞http://blog.csdn.net/levera ...

  6. android opengl es 纹理 不同设备 白色,android – OpenGL ES 2.0纹理没有在某些设备上显示...

    早上好,这是2个纹理非幂的典型例子. 由于多种原因,纹理在分辨率上需要2的幂,这是一个非常常见的错误,每个人都碰巧陷入这个陷阱:)我也是. 2个纹理的非功率在某些设备/ GPU上运行平稳的事实,仅仅取 ...

  7. 使用Android OpenGL ES 2.0绘图之三:绘制形状

    传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 在定义好待绘制的形状之后,就要开始绘制它们了.使用OpenGL ES 2.0绘制形状可 ...

  8. android opengl es 2.0 编程指南,Android OpenGL ES 2.0 初次体验

    本文目录 一. OpenGL ES是什么? 二. OpenGL ES的版本 三. EGL是什么? 四. 需要知道的两个方法 五. 在Android中使用OpenGL ES的步骤 六. 例子1:简单的程 ...

  9. 使用Android OpenGL ES 2.0绘图之二:定义形状

    传送门☞Android兵器谱☞转载请注明☞http://blog.csdn.net/leverage_1229 传送门☞系统架构设计☞转载请注明☞http://blog.csdn.net/levera ...

最新文章

  1. 仿qq邮箱源码程序_巧用小程序·云开发实现邮件发送功能丨实战
  2. LeetCode:155. 最小栈
  3. 深度学习String、StringBuffer、StringBuilder
  4. 技术分享|手机推送原理剖析指南
  5. I - The Mad Mathematician FZU - 2042(未解决)
  6. 安装Sphinx 和 Thinking Sphinx
  7. ionic3 生命周期
  8. 优先队列 STL (转)
  9. 鼎信诺取数oracle,鼎信诺审计前端取数讲解(最新).ppt
  10. 有限元法 有限差分法 有限体积法
  11. python 调用海康linux下psdatacall_demo,实现获取视频码流并返回到python,以及上传信息到人脸库的方法
  12. 3步教你学会cocos creator 物理引擎
  13. VSCode下载及安装
  14. 测绘人真实故事 | 放弃上万月薪从私企跳回国企
  15. 改变屏幕分辨率的小程序
  16. IO流常用类使用详解
  17. 前端项目中使用js-beautify格式化、美化js代码
  18. 蓝牙核心协议学习 -- 基带协议(Baseband)
  19. Office拼音助手第二版(一键给文档里的汉字注音)
  20. js生成二维码,web页面,移动h5页添加微信qq分享功能

热门文章

  1. marquee 的浏览器兼容性
  2. 订餐系统之同步口碑外卖商家菜单与点点送订单
  3. c语言程序设计拉丁方阵结构图,C语言程序设计100例之(29):拉丁方阵
  4. 中国有句俗语叫“三天打鱼两天晒网”。某人从2010年1月1日起开始“三天打鱼两天晒网”,问这个人在以后的某一天中是“打鱼”还是“晒网”
  5. 采用EasyNVR网页无插件互联网直播平台对接海康摄像头如何通过SDK将视频在前端网页上进行播放?
  6. 计算机组成与维修考试试题,计算机组成原理试题与答案(考试资料)
  7. 让mysql的自增id重新从1开始
  8. 基于Matlab的脉冲多普勒雷达仿真
  9. 天融信防火墙重置配置_天融信防火墙认证配置
  10. ALSA声卡驱动中的DAPM详解之一:kcontrol