关于opengl-es:Opengl-ES之PBO
叨叨一句几句对于Opengl的系列曾经有较长的一段时间没有更新了,然而这个系列还远没有到结束境地,后续至多还有对于Opengl矩阵变换、YUV与RGB互转、Opengl水印贴图、Opengl转场动画等主题文章。 断更的次要起因如果给本人找个借口的话能够说是工作比价忙,如果说的比拟事实一点就是本人懒且没啥能源,毕竟写技术博客文章是一件工夫老本投入很大,而收益产出极小的一件事件... 进入正题... 理解过Opengl的童鞋们都晓得,在Opengl中存在这个各种O,例如VAO、VBO、FBO等,而呈现各种各样的O个别都是因为思考到性能的起因。 明天咱们要介绍的配角PBO,它和之前咱们介绍VBO很像,理解完PBO之后童鞋们能够比照一下PBO与VBO的差别点。 上面从两个方面介绍PBO,什么是PBO以及如何应用PBO。 本文首发于微信公总号号:思想觉悟 更多对于音视频、FFmpeg、Opengl、C++的原创文章请关注微信公众号:思想觉悟 什么是PBOPBO(Pixel Buffer Object像素缓冲对象)。在理解什么是PBO之前,咱们先来理解一下为什么会呈现PBO这么一个货色? 所谓存在即正当,用倒退的眼光看问题,PBO的呈现必定是为了代替某种货色,或者是为了解决某个问题。 在应用Opengl的时候常常须要在GPU和CPU之间传递数据,例如在应用Opengl将YUV数据转换成RGB数据时就须要先将YUV数据上传到GPU,个别应用函数glTexImage2D,处理完毕后再将RGB后果数据读取到CPU,这时应用函数glReadPixels即可将数据取回。然而这两个函数都是比拟迟缓的,特地是在数据量比拟大的时候。PBO就是为了解决这个拜访慢的问题而产生的。 PBO能够让咱们通过一个内存指针,间接拜访显存(GPU)的数据,咱们将这块内存指针称作缓冲区。咱们能够通过函数glMapBuffer失去它的内存指针,而后就对这块缓冲区的数据能够随心所欲了。 例如应用函数glReadPixels本来是要传一个内存指针进去的,然而有了缓冲区,它就能够把数据间接复制到缓冲区中去,而不是复制到内存条中去,这样就大大提高了数据的传递效率。 PBO的次要长处是通过间接内存拜访的形式与显存进行疾速像素数据传输,而无需占用CPU周期。 可能看到这张图你没什么感觉,然而比照看看上面这张CPU与GPU间接传递数据的图你就会有所发现了: 留神:PBO是OpenGL ES 3.0开始提供的一种形式,次要利用于从内存疾速复制纹理到显存,或从显存复制像素数据到内存。 PBO的应用形式既然PBO这么有效率,那么咱们在什么状况下可能会用到PBO呢?有个常见的例子,例如咱们在安卓上开发Camera利用录制视频时,如果须要用到x264进行软编码的话可能就会用到PBO,首先咱们将相机纹理图像送到Surface渲染显示,而后将Surface数据应用PBO的形式读取解决送到X264编码器中进行编码,当然在安卓上你也能够应用ImageReader... 上面咱们来介绍下PBO的应用形式。 PBO的创立和初始化相似于VBO,然而在应用的时候须要用到GL_PIXEL_UNPACK_BUFFER 和GL_PIXEL_PACK_BUFFER 这两个令牌,其中GL_PIXEL_UNPACK_BUFFER绑定示意该PBO用于将像素数据从程序(CPU)传送到OpenGL中;绑定为GL_PIXEL_PACK_BUFFER示意该PBO用于从OpenGL中读回像素数据。 Pbo创立先上代码,跟着正文看 void PBOOpengl::initPbo() { int imgByteSize = imageWidth * imageHeight * 4; // RGBA glGenBuffers(1, &uploadPboId); // 绑定pbo glBindBuffer(GL_PIXEL_UNPACK_BUFFER, uploadPboId); // 设置pbo内存大小 // 这一步非常重要,第2个参数指定了这个缓冲区的大小,单位是字节,肯定要留神 // 而后第3个参数是初始化用的数据,如果你传个内存指针进去,这个函数就会把你的 // 数据复制到缓冲区里,咱们这里一开始并不需要什么数据,所以传个nullptr就行了 glBufferData(GL_PIXEL_UNPACK_BUFFER, imgByteSize, nullptr, GL_STREAM_DRAW); // 解除绑定 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glGenBuffers(1, &downloadPboId); glBindBuffer(GL_PIXEL_PACK_BUFFER, downloadPboId); glBufferData(GL_PIXEL_PACK_BUFFER, imgByteSize, nullptr, GL_STREAM_DRAW); // 解除绑定 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); LOGD("uploadPboId:%d---downloadPboId:%d---imgByteSize:%d", uploadPboId, downloadPboId, imgByteSize);}下面的代码创立了两个PBO,其中uploadPboId用于纹理上传,downloadPboId用于纹理下载。创立好PBO之后而后应用两个PBO专用的令牌进行绑定,之后就调用glBufferData给PBO调配缓冲区,当然,你也能够在应用的时候先进行绑定,而后从新调用glBufferData调配新的缓冲区。 ...