在上一篇文章中,主要介紹了OpenGL ES基礎(chǔ)桥嗤,了解了OpenGL ES的基礎(chǔ)之后须妻,我們就可以開始學(xué)習(xí)GPUImage的源碼了。本文將主要介紹GPUImage的整體框架泛领,渲染的流程以及幾個重要的類和協(xié)議荒吏。
輸入和輸出
任何一個框架或者程序的出發(fā)點都是輸入和輸出,GPUImage中最重要的也是這兩個元素渊鞋。在框架層面上說绰更,輸入應(yīng)該是一張圖片,一個視頻锡宋,一個UI元素或者一個數(shù)據(jù)流儡湾。而輸出也同樣應(yīng)該是一個處理完成了的圖片,視頻或者數(shù)據(jù)流执俩。
在GPUImage內(nèi)部的實現(xiàn)中徐钠,主要的實現(xiàn)思想也是將一個圖片的內(nèi)容放置到frameBuffer中,然后將這個frameBuffer在濾鏡鏈中進(jìn)行傳遞役首,并且處理尝丐。因此,每一個濾鏡既可以作為一個輸入(GPUImageInput)宋税,也可以作為一個輸出(GPUImageOutput)存在摊崭。
GPUImageInput
GPUImageInput是一個Protocol,實現(xiàn)這個Protocol的類需要實現(xiàn)的方法主要都是接收上一個GPUImageOutput的frameBuffer相關(guān)的方法杰赛,以及處理當(dāng)上一個GPUImageOutput處理完一幀之后收到的通知呢簸。實現(xiàn)了GPUImageInput接口的類包括了所有的Filter,F(xiàn)ilterGroup,GPUImageView根时,GPUImageMovieWriter瘦赫。因為它們都需要獲取之前一個Output處理得到的結(jié)果,從而進(jìn)行渲染蛤迎。
GPUImageOutput
GPUImageOutput是一個基類确虱,實現(xiàn)了一些基本方法,比如通用的將下一個GPUImageInput添加到FilterChain中的方法替裆。同時在每一個GPUImageOutput中校辩,都需要維護(hù)一個GPUImageFrameBuffer,這個就是Output真正的輸出辆童。GPUImageOutput還提供了從當(dāng)前的FrameBuffer中獲取圖片的一系列方法宜咒。常用的GPUImageOutput的子類有:所有的Filter,F(xiàn)ilterGroup把鉴,GPUImagePicture故黑,GPUImageMovie,GPUImageUIElement等等庭砍。
每一個GPUImageOutput對象通過調(diào)用addTarget:atTextureLocation:方法场晶,將自己的輸出frameBuffer以及相關(guān)的信息告訴FilterChain中的下一個Input;
因此怠缸,每一個FilterChain的第一個元素都是GPUImageOutput的子類诗轻,比如GPUImagePicture,GPUImageMovie等等凯旭。這個和我們上面說的輸入和輸出并不沖突概耻,因為任何一個圖像處理的最初的一個元素,必須要能夠生成并且產(chǎn)出一個FrameBuffer罐呼,才能夠給后面的濾鏡使用。
而最終用于顯示的GPUImageView則是一個GPUImageInput侦高,因為它只需要接收處理完的圖片進(jìn)行顯示嫉柴,而不需要將結(jié)果繼續(xù)傳遞給其他的Input。
GPUImageFrameBuffer
GPUImageFrameBuffer提供了在GPUImageOutput和GPUImageInput進(jìn)行數(shù)據(jù)傳遞的媒介奉呛。每個GPUImageFrameBuffer都有一個自己的OpenGL Texture计螺,這個Texture作為下一個Input的Texel來源。多數(shù)的GPUImageFrameBuffer包含一個OpenGL FrameBuffer瞧壮,這個FrameBuffer用來離屏渲染登馒,并且將渲染的結(jié)果放置到Texture中。每個GPUImageOutput都包含了至少一個GPUImageFrameBuffer對象咆槽,而每個GPUImageInput都實現(xiàn)了一個setInputFramebuffer:atIndex:方法陈轿,來接收上一個Output處理完的紋理。
GPUImageFilter
GPUImageFilter是一個GPUImageOutput的子類,同時實現(xiàn)了GPUImageInput協(xié)議麦射。是整個GPUImage框架的核心蛾娶。GPUImage除了實現(xiàn)了Input和Output的功能之外,還實現(xiàn)了基本的渲染功能潜秋。因此蛔琅,每個GPUImageFilter都包含了一個GLProgram的對象,這個對象實現(xiàn)了OpenGL ES相關(guān)的渲染峻呛。
GLProgram
GLProgram是對OpenGL ES的program的面向?qū)ο蠓庋b罗售,包括了Vertex Shader,F(xiàn)ragmentShader的加載钩述,program的link以及對attribute和uniform的獲取和管理寨躁。由于GPUImage處理的對象主要是2D的圖片,因此切距,作者將一些常用的Attributes以及Uniform做了固定的命名規(guī)范處理朽缎,從而實現(xiàn)了簡單的面向?qū)ο蠓庋b。
渲染過程
根據(jù)上面的介紹谜悟,我們可以總結(jié)出GPUImage總體的渲染流程话肖;
1. 首先我們需要創(chuàng)建一個GPUImageOutput,作為需要被處理的對象來源葡幸,常用的有:
GPUImagePicture:使用圖片作為處理對象最筒;
GPUImageMovie:使用視頻作為處理對象;
GPUImageUIElement:使用UIElement作為處理對象蔚叨;
GPUImageVideoCamera: 使用相機(jī)捕捉到的圖像作為處理對象床蜘;
2. 有了處理的對象之后,我們需要根據(jù)我們的需求蔑水,創(chuàng)建不同種類的Filter邢锯,并且通過GPUImageOutput的addTarget:atTextureLocation:方法,將這些Filter添加到FilterChain中搀别;
3. 如果我們需要顯示處理完的結(jié)果或者保存這個結(jié)果的話丹擎,我們還需要將處理完的結(jié)果輸出到一個GPUImageInput中。常用的有:
GPUImageView:將處理結(jié)果顯示到一個View上歇父,這個View可以實時顯示處理的結(jié)果蒂培;
GPUImageMovieWriter:將處理的結(jié)果保存到一個視頻文件中;
圖片:如果最終沒有一個顯示的Target榜苫,我們也可以通過GPUImageOutput中的一系列newCGImageFromFrameBuffer方法护戳,直接獲取到當(dāng)前GPUImageOutput處理的結(jié)果。
4. 調(diào)用第一步素材的開始處理方法垂睬,讓處理過程開始:
[picture processImage];
[movie startProcessing];
[element update];
[camera startCapture];
到這里媳荒,整個GPUImage渲染的流程就結(jié)束了抗悍,就可以坐等輸出的結(jié)果啦。當(dāng)然本文只是介紹了GPUImage的整個渲染流程肺樟,具體的每一個元素會在之后的具體解析中再詳細(xì)介紹檐春。