前言
學(xué)了OpenGL,OpenGLES后,去閱讀了GPUImage的源碼,使用了一段時間,接下來,記錄一下我對GPUImage使用和源碼閱讀的一些分析吧。
相關(guān)引用
從0打造一個GPUImage(6)-GPUImage的多濾鏡處理邏輯
GPUImage結(jié)構(gòu)
對于GPUImage,可以分為
- GLProgram 用于加載shader,鏈接program的類
- GPUImageContext 用于OpenGLContext上下文管理的
- GPUImageFrameBuffer 用于frameBuffer的管理,GPUImage的濾鏡鏈靠的就是傳遞
GPUImageFrameBuffer
- GPUImageFrameBufferCache 用于緩存frameBuffer的類,會根據(jù)texture的option屬性,已經(jīng)size生成key,作為緩存
- Sources 可以理解為萬惡之源吧,所有的渲染處理,都是從這里開始的,必須繼承GPUImageOutput
- Filter 濾鏡類 既繼承了GPUImageOutput,也遵守GPUImageInput的類,從而實現(xiàn)GPUImageOutput -> filter -> filter -> GPUImageInput的濾鏡鏈的關(guān)鍵
- Outputs,實現(xiàn)了GPUImageInput的組件,是渲染結(jié)果的終點
GPUImage的濾鏡鏈
上面也提了,所謂的GPUImage濾鏡鏈就是
GPUImageOutput -> filter -> filter -> GPUImageInput
GPUImageOutput
通過target數(shù)組(里面都是實現(xiàn)GPUImageInput
組件),組成了濾鏡鏈的關(guān)系,我們需要牢牢的記住這個濾鏡鏈的關(guān)系,這樣開發(fā)的時候,我們就知道如何Debug,如何實現(xiàn)我們需要的效果。那么問題來了,為什么GPUImage可以實現(xiàn)這樣的濾鏡鏈呢?
濾鏡鏈實現(xiàn)的原理
這里我們先拋開GPUImage,用OpenGL ES去實現(xiàn)一個具有濾鏡疊加效果的Demo,這里的Demo我是參考葉孤城的這篇文章,從0打造一個GPUImage(6)-GPUImage的多濾鏡處理邏輯
Demo需要實現(xiàn)的效果,是將一張圖片,先后通過疊加亮度濾鏡
,飽和度濾鏡
最后顯示在屏幕上。
使用GPUImage的渲染步驟
- 通過
GPUImagePicture
加載圖片(這里就是source) - source addTarget
亮度濾鏡
-
亮度濾鏡
傳遞渲染結(jié)果給飽和度濾鏡
-
飽和度濾鏡
傳遞給GPUImageView,GPUImageView顯示渲染結(jié)果,
使用OpenGLES的渲染步驟
那么對應(yīng)的OpenGLES,我們會怎么做呢?首先我們需要以下東西
- 一個源,其實就是將圖片信息加載為紋理的過程,這里對應(yīng)
GPUImagePicture
- 3個frameBuffer,前兩個掛載
亮度濾鏡
和飽和度濾鏡
的texture
,通過glFramebufferTexture2D
綁定texture到frameBuffer上,最后一個frameBuffer掛載的是renderBuffer用于顯示
// 綁定texture
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, brightnessTexture, 0)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, saturationTexture, 0)
// 綁定renderBuffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderBuffer);
- 3個Program,前兩個Program用于加載
亮度濾鏡
和飽和度濾鏡
的frameShader文件(這里就相當(dāng)于GPUImageInput
),最后一個Program加載的frameShader只需要把rgb信息從紋理中取出,然后展示就行了(這里就相當(dāng)于GPUImageView
)。
從以上的步驟,我們可以總結(jié)以下結(jié)論
- 1、源總是會產(chǎn)生
texture
開始傳遞的,這里其實就是GPUImageOutput的職責(zé) - 2、每個濾鏡Filter都是通過傳遞frameBuffer掛載
texture
來傳遞渲染結(jié)果的(這里的濾鏡對應(yīng)一個program,一個frameBuffer) - 3、對于需要顯示的渲染結(jié)果的
GPUImageInput
,例如GPUImageView
,需要依賴frameBuffer掛載renderBuffer進(jìn)行顯示
對于這個Demo的一個流程圖,可以參考從0打造一個GPUImage(6)-GPUImage的多濾鏡處理邏輯的一幅圖,Demo的詳細(xì)實現(xiàn)請看原文吧。
總結(jié)
以上就是GPUImage對于濾鏡鏈的實現(xiàn)原理,只有你懂了OpenGL ES的渲染流程,才能徹底的明白GPUImage的濾鏡鏈的原理。所以時時刻刻記住以下關(guān)系
GPUImageOutput -> filter -> filter -> GPUImageInput
當(dāng)然也可以存在多個Source,多個Input的情況,例如要給一個視頻添加水印,用GPUImageMovie
用于輸出視頻紋理,用GPUImageUIElement
輸出UI空間的紋理,通過一個filter進(jìn)行Blend,最后用一個GPUImageView
進(jìn)行預(yù)覽,用GPUImageMovieWriter
進(jìn)行輸出,濾鏡鏈關(guān)系如下
GPUImageOutput -> filter -> filter -> GPUImageInput
↑ ↓
GPUImageOutput -----> GPUImageInput