美文网首页
GPUImage源码解析 -- 框架概览

GPUImage源码解析 -- 框架概览

作者: Danielhhs | 来源:发表于2018-01-16 17:39 被阅读0次

    在上一篇文章中,主要介绍了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的整个渲染流程,具体的每一个元素会在之后的具体解析中再详细介绍。

    相关文章

      网友评论

          本文标题:GPUImage源码解析 -- 框架概览

          本文链接:https://www.haomeiwen.com/subject/tevfoxtx.html