OpenGL pixel_buffer_object 扩展非常接近 vertex_buffer_object
它只是扩展出 vertex_buffer_object扩展,以便不仅将顶点数据并且将像素数据也存储到缓冲区对象中。这种存储像素数据的缓冲对象称为像素缓冲对象(PBO)。
pixel_buffer_object扩展借用了所有 VBO 框架和 API,此外还添加了 2 个额外的“target”令牌。
这些令牌协助 PBO 内存管理器(OpenGL 驱动程序)确定缓冲对象的最佳位置;系统内存、共享内存或显存。
此外,target令牌定义了绑定的 PBO 将用于 2 个不同的操作:GL_PIXEL_PACK_BUFFER 将像素数据传输到 PBO,或 GL_PIXEL_UNPACK_BUFFER将像素数据从 PBO 传输。

例如,
1、glReadPixels()和glGetTexImage() 是“pack”像素操作,
2、而 glDrawPixels()glTexImage2D()和glTexSubImage2D() 是“unpack”操作。
3、当 PBO 与 GL_PIXEL_PACK_BUFFER 令牌绑定时,**glReadPixels()**从 OpenGL 帧缓冲区读取像素数据并将数据写入(打包)到 PBO。
4、当 PBO 与 GL_PIXEL_UNPACK_BUFFER 令牌绑定时,**glDrawPixels()**从 PBO 读取(解包)像素数据并将它们复制到 OpenGL 帧缓冲区。

PBO 的主要优点是通过 DMA(直接内存访问)与图形卡进行快速像素数据传输,而无需占用 CPU 周期。而且,PBO 的另一个优点是异步 DMA 传输。


相反,在上图中,图像源可以直接加载到 PBO 中,该 PBO 由 OpenGL 控制。 CPU 仍然涉及将源加载到 PBO,但不会将像素数据从 PBO 传输到纹理对象。

相反,GPU(OpenGL 驱动程序)管理将数据从 PBO 复制到纹理对象。这意味着 OpenGL 在不浪费 CPU 周期的情况下执行 DMA 传输操作。此外,OpenGL 可以安排异步 DMA 传输以供以后执行。
因此,glTexImage2D() 立即返回,CPU 可以执行其他操作而无需等待像素传输完成。
有两种主要的 PBO 方法可以提高像素数据传输的性能:流式纹理更新(streaming texture update)和从帧缓冲区异步回读(asynchronous read_back from the framebuffer)。

上图为原始不使用PBO方法对比
让我们将传统的纹理传输方法与使用像素缓冲区对象进行比较。上图是从图像源(图像文件或视频流)加载纹理数据的常规方式。材质源首先加载到系统内存中,然后使用 glTexImage2D() 从系统内存复制到 OpenGL 纹理对象。这 2 个传输过程(加载和复制)都由 CPU 执行。

Creating PBO

如前所述,Pixel Buffer Object 借用了Vertex Buffer Object 的所有 API。唯一的区别是 PBO 有 2 个额外的令牌:GL_PIXEL_PACK_BUFFERGL_PIXEL_UNPACK_BUFFER

GL_PIXEL_PACK_BUFFER 用于将像素数据从 OpenGL 传输到您的应用程序,而 GL_PIXEL_UNPACK_BUFFER表示将像素数据从应用程序传输到 OpenGL。OpenGL 参考这些标记来确定 PBO 的最佳内存空间,例如,用于上传(unpacking)纹理的显存,或用于读取(pack)帧缓冲区的系统内存。但是,这些目标标记只是举例。 具体实现时OpenGL 驱动程序为您决定合适的位置。

创建PBO的3个步骤:

1、使用**glGenBuffers()**生成一个新的缓冲区对象。
2、使用 **glBindBuffer()**绑定缓冲区对象。
3、使用 glBufferData()将像素数据复制到缓冲区对象。
如果在glBufferData() 中指定指向源数组的为 NULL 指针,则 PBO 仅分配具有给定数据大小的内存空间。 glBufferData() 的最后一个参数是 PBO 的另一个性能提示,用于提供如何使用缓冲区对象。

GL_STREAM_DRAW用于流式纹理上传,GL_STREAM_READ 用于异步帧缓冲区回读。

请查看 VBO文档 以获取更多详细信息。

**

Mapping PBO

**
PBO 提供了一种内存映射机制,将OpenGL 控制的缓冲区对象映射到客户端的内存地址空间。因此,客户端可以使用**glMapBuffer()**和 **glUnmapBuffer()**修改缓冲区对象的一部分或整个缓冲区。

void glMapBuffer(GLenum target, GLenum access)*
GLboolean glUnmapBuffer(GLenum target)

如果映射成功,**glMapBuffer()**将返回指向缓冲区对象的指针。否则返回NULL。target参数是 GL_PIXEL_PACK_BUFFERGL_PIXEL_UNPACK_BUFFER。第二个参数,access 指定如何处理映射的缓冲区;从 PBO 读取数据 (GL_READ_ONLY),将数据写入 PBO (GL_WRITE_ONLY),或两者 (GL_READ_WRITE)。

如果 GPU 仍在使用缓冲区对象,则 glMapBuffer() 将不会返回,直到 GPU 使用相应的缓冲区对象完成其工作。为了避免这种停顿(等待),请在 glMapBuffer() 之前使用 NULL 指针调用 glBufferData()。然后,OpenGL 将丢弃旧缓冲区,并为缓冲区对象分配新的内存空间。

使用 PBO 后,缓冲区对象必须使用 glUnmapBuffer() 取消映射。如果成功,**glUnmapBuffer()**返回 GL_TRUE。否则,它返回 GL_FALSE。

**

Others

**
为了最大化流传输性能,您可以使用多个像素缓冲区对象。该图显示同时使用 2 个 PBO; **glTexSubImage2D()**从 PBO 复制像素数据,同时将纹理源写入另一个 PBO。对于第 n 帧,PBO 1 用于 glTexSubImage2D(),PBO 2 用于获取新的纹理源。对于第 n+1 帧,2 个像素缓冲区正在切换角色并继续更新纹理。由于异步 DMA 传输,更新和复制过程可以同时执行。 CPU 将纹理源更新到 PBO,而 GPU 从另一个 PBO 复制纹理。

传统的 glReadPixels() 会阻塞管道并等待所有像素数据传输完毕。然后,它将控制权返回给应用程序。相反,带有 PBO 的 glReadPixels() 可以调度异步 DMA 传输并立即返回而不会停顿。因此,应用程序 (CPU) 可以立即执行其他进程,同时通过 OpenGL (GPU) 使用 DMA 传输数据。此演示使用 2 个像素缓冲区。在第 n 帧,应用程序使用 glReadPixels() 将像素数据从 OpenGL 帧缓冲区读取到 PBO 1,并在 PBO 2 中处理像素数据。这些读取和处理可以同时执行,因为 glReadPixels() 到 PBO 1 立即返回,CPU 立即开始处理 PBO 2 中的数据。并且,我们在每一帧上在 PBO 1 和 PBO 2 之间交替。

像素缓冲对象(PBO)相关推荐

  1. OpenGL深入探索——像素缓冲区对象 (PBO)

    英文原文地址 wiki解释 概述 OpenGL ARB_pixel_buffer_object 扩展与ARB_vertex_buffer_object.很相似.为了缓冲区对象不仅能存储顶点数据,还能存 ...

  2. Android OpenGL ES 3.0 PBO像素缓冲区对象

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

  3. Opengl-帧缓冲(一个新的缓冲对象,想一下深度和模板缓冲)

    OpenGL中的缓冲只是一个管理特定内存块的对象,没有其它更多的功能了. 首先我们明确一个原理或者道理,不论是什么缓冲,深度也好,模板也罢.再往前说的顶点数据的颜色缓冲.都是一个存储的单元,都是一个存 ...

  4. GLSL着色器实现多重纹理与帧缓冲对象(FBO)

    还记得我前面几篇博客上写的东西都是将纹理直接渲染到屏幕上,就是产生一个和纹理尺寸大小相同的窗口进行渲染,那么渲染完了就正好完整的显示了纹理图案.但是在做数值计算的时候,一般是不需要输出到屏幕上的,这就 ...

  5. OpenGL学习脚印: 帧缓冲对象(Frame Buffer Object)

    写在前面 一直以来,我们在使用OpenGL渲染时,最终的目的地是默认的帧缓冲区,实际上OpenGL也允许我们创建自定义的帧缓冲区.使用自定义的帧缓冲区,可以实现镜面,离屏渲染,以及很酷的后处理效果.本 ...

  6. OpenGL 基本帧缓冲对象实例

    OpenGL 基本帧缓冲对象实例 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <vmath.h> #include <sb7 ...

  7. 【OpenGL学习笔记五】 索引缓冲对象EBO

    在绘制一些图形的时候比如正方体,正方体的顶点是有很多重合的,如果为每个顶点都分配内存那么就比较浪费内存了. OpenGL通过索引缓冲对象来解决这个问题,做到重复的顶点只需要分配一次内存,再绘图的时候后 ...

  8. opengl之高级GLSL(2)-接口块,Uniform缓冲对象,Uniform块布局等

    接口块 当程序变得更大时,你希望发送的可能就不只是几个变量了,它还可能包括数组和结构体. 为了帮助我们管理这些变量,GLSL为我们提供了一个叫做接口块(Interface Block)的东西,来方便我 ...

  9. OpenGL学习脚印:缓冲对象相关函数的使用(buffer object function)

    OpenGL中还包含除了我们前面介绍的VAO,VBO,EBO等其他类型的缓冲对象.本文将通过简洁.可靠的例子说明一些重要方法的使用,以辅助学习这些方法.本文的目的不是写成详细而厚重的手册,对于文中未详 ...

最新文章

  1. 【机器学习】RNN循环神经网络
  2. 万粉博主推荐,微信小程序 +Flask 后端调用 AnimeGanV2
  3. 以太经典(ETC)逆势上涨,将逆袭反超以太坊(ETH)?
  4. 多线程:happens-before原则
  5. 只需四步完成java JDK1.8的下载安装与配置【图文详解】
  6. 减去字符串_leetcode刷题844比较含退格的字符串(带代码解析,带知识点回顾)
  7. mysql 生成日历表_如何在SQL中创建100年的日历表
  8. [科普]关于文件头的那些事
  9. 分享Monaco.ttf字体(Mac样式)
  10. cad 2020安装失败,怎么完全彻底卸载删除清理干净cad 2020各种残留注册表和文件? 【转载】
  11. Python完成电脑记事本软件的详细过程
  12. Linux系统下下载Tomcat详细步骤。
  13. 家庭理财项目 分析
  14. 网站页面设计的原则有哪些呢?
  15. Android 状态栏适配
  16. ggplot2在一幅图上画两条曲线
  17. 计算机二级教程书pdf MS,全国计算机等级考试二级教程MS Office高级应用教学大纲4.pdf...
  18. 修改电脑ip为固定ip不能上网
  19. python计算营业额代码_python计算营业额的代码_python 统计代码行数简单实例
  20. 有没有什么赚钱的副业?分享,适合学生赚钱的30个副业!

热门文章

  1. 【老生谈算法】matlab实现图像拼接算法源码——图像拼接
  2. transformer
  3. C++编程思想 第1卷 第9章 内联函数 内联函数 访问器和修改器
  4. Java的ArrayList集合使用---唐代诗人斗地主!!!
  5. beetle进行同屏500物体广播测试
  6. ORACLE PSU AND OPATTCH UPGRADE
  7. 脱壳工具:frida-dexdump的使用详解
  8. 卷积公式和分布函数去解决Z=X+Y,Z=XY,Z=Y/X等Z的概率密度函数以及如何确定他们的范围
  9. Peercast源代码分析
  10. 2021年国际天然气展会将在新加坡以现场方式举行,壳牌、雪佛龙等确认参展