上一章探讨了如何采用SurfaceTexture+GLSurfaceView显示YUV数据,减少了片段着色器的工作量和代码量,但是采用GLSL采用的外部纹理真正的内容是在物理内存中,GPU只负责维护元数据,这样就增加了GPU取数据的时间,若进行一些运算密集的算法例如高斯滤波,每次都会到外部纹理取数据,这样则会造成明显的卡顿,所以仅采用外部纹理实现实时滤镜行不通。同时采用JNI格式转换随着预览分辨率提高时间也达不到要求,采用Shader转换则每次加权计算都需要进行格式转换,也增加了运算量。
好在OpenGL允许用户创建帧缓存对象,可以将数据渲染到纹理。因此我们可以将对应相机预览图像的外部纹理先渲染到内部纹理中,剩下的滤镜再绑定到该纹理,对其进行操作,这样就增加渲染速度,经实验帧数达到要求。
以下代码和思路参考GPUImage中的GPUImageFilterGroup,因为Android平台采用的是OpenGL ES,与OpenGL略有不同。
一.分配帧缓冲对象:
1)创建帧缓冲对象:
有N+1个滤镜(其中第一个从外部纹理接收的无滤镜效果),就需要分配N个帧缓冲对象,首先创建大小为N的两个数组mFrameBuffers和mFrameBufferTextures,分别用来存储缓冲区id和纹理id,通过GLES20.glGenFramebuffers(1, mFrameBuffers, i)来创建帧缓冲对象