在上一篇文章中,主要介绍了OpenGL ES基础,了解了OpenGL ES的基础之后,我们就可以开始学习GPUImage的源码了。本文将主要介绍GPUImage的整体框架,渲染的流程以及几个重要的类和协议。
输入和输出
任何一个框架或者程序的出发点都是输入和输出,GPUImage中最重要的也是这两个元素。在框架层面上说,输入应该是一张图片,一个视频,一个UI元素或者一个数据流。而输出也同样应该是一个处理完成了的图片,视频或者数据流。
在GPUImage内部的实现中,主要的实现思想也是将一个图片的内容放置到frameBuffer中,然后将这个frameBuffer在滤镜链中进行传递,并且处理。因此,每一个滤镜既可以作为一个输入(GPUImageInput),也可以作为一个输出(GPUImageOutput)存在。
GPUImageInput
GPUImageInput是一个Protocol,实现这个Protocol的类需要实现的方法主要都是接收上一个GPUImageOutput的frameBuffer相关的方法,以及处理当上一个GPUImageOutput处理完一帧之后收到的通知。实现了GPUImageInput接口的类包括了所有的Filter,FilterGroup,GPUImageView,GPUImageMovieWriter。因为它们都需要获取之前一个Output处理得到的结果,从而进行渲染。
GPUImageOutput
GPUImageOutput是一个基类,实现了一些基本方法,比如通用的将下一个GPUImageInput添加到FilterChain中的方法。同时在每一个GPUImageOutput中,都需要维护一个GPUImageFrameBuffer,这个就是Output真正的输出。GPUImageOutput还提供了从当前的FrameBuffer中获取图片的一系列方法。常用的GPUImageOutput的子类有:所有的Filter,FilterGroup,GPUImagePicture,GPUImageMovie,GPUImageUIElement等等。
每一个GPUImageOutput对象通过调用addTarget:atTextureLocation:方法,将自己的输出frameBuffer以及相关的信息告诉FilterChain中的下一个Input;
因此,每一个FilterChain的第一个元素都是GPUImageOutput的子类,比如GPUImagePicture,GPUImageMovie等等。这个和我们上面说的输入和输出并不冲突,因为任何一个图像处理的最初的一个元素,必须要能够生成并且产出一个FrameBuffer,才能够给后面的滤镜使用。
而最终用于显示的GPUImageView则是一个GPUImageInput,因为它只需要接收处理完的图片进行显示,而不需要将结果继续传递给其他的Input。
GPUImageFrameBuffer
GPUImageFrameBuffer提供了在GPUImageOutput和GPUImageInput进行数据传递的媒介。每个GPUImageFrameBuffer都有一个自己的OpenGL Texture,这个Texture作为下一个Input的Texel来源。多数的GPUImageFrameBuffer包含一个OpenGL FrameBuffer,这个FrameBuffer用来离屏渲染,并且将渲染的结果放置到Texture中。每个GPUImageOutput都包含了至少一个GPUImageFrameBuffer对象,而每个GPUImageInput都实现了一个setInputFramebuffer:atIndex:方法,来接收上一个Output处理完的纹理。
GPUImageFilter
GPUImageFilter是一个GPUImageOutput的子类,同时实现了GPUImageInput协议。是整个GPUImage框架的核心。GPUImage除了实现了Input和Output的功能之外,还实现了基本的渲染功能。因此,每个GPUImageFilter都包含了一个GLProgram的对象,这个对象实现了OpenGL ES相关的渲染。
GLProgram
GLProgram是对OpenGL ES的program的面向对象封装,包括了Vertex Shader,FragmentShader的加载,program的link以及对attribute和uniform的获取和管理。由于GPUImage处理的对象主要是2D的图片,因此,作者将一些常用的Attributes以及Uniform做了固定的命名规范处理,从而实现了简单的面向对象封装。
渲染过程
根据上面的介绍,我们可以总结出GPUImage总体的渲染流程;
1. 首先我们需要创建一个GPUImageOutput,作为需要被处理的对象来源,常用的有:
GPUImagePicture:使用图片作为处理对象;
GPUImageMovie:使用视频作为处理对象;
GPUImageUIElement:使用UIElement作为处理对象;
GPUImageVideoCamera: 使用相机捕捉到的图像作为处理对象;
2. 有了处理的对象之后,我们需要根据我们的需求,创建不同种类的Filter,并且通过GPUImageOutput的addTarget:atTextureLocation:方法,将这些Filter添加到FilterChain中;
3. 如果我们需要显示处理完的结果或者保存这个结果的话,我们还需要将处理完的结果输出到一个GPUImageInput中。常用的有:
GPUImageView:将处理结果显示到一个View上,这个View可以实时显示处理的结果;
GPUImageMovieWriter:将处理的结果保存到一个视频文件中;
图片:如果最终没有一个显示的Target,我们也可以通过GPUImageOutput中的一系列newCGImageFromFrameBuffer方法,直接获取到当前GPUImageOutput处理的结果。
4. 调用第一步素材的开始处理方法,让处理过程开始:
[picture processImage];
[movie startProcessing];
[element update];
[camera startCapture];
到这里,整个GPUImage渲染的流程就结束了,就可以坐等输出的结果啦。当然本文只是介绍了GPUImage的整个渲染流程,具体的每一个元素会在之后的具体解析中再详细介绍。