GPUImage 是一個基於 GPU 圖像和視頻處理的開源 iOS 框架。因爲使用 GPU 來處理圖像和視頻,因此速度很是快,它的做者 BradLarson 稱在 iPhone4 上其處理速度是使用 CPU 來處理的 100 倍 (CoreImage 也能使用 GPU 來處理圖像,但我以爲 CoreImage 仍是慢)。除了速度上的優點,GPUImage 還提供了不少很棒的圖像處理濾鏡,但有時候這些基本功能仍然沒法知足實際開發中的需求,不用擔憂 GPUImage 支持自定義濾鏡。html
GPUImage 自定義濾鏡須要使用 OpenGL 着色語言( GLSL )編寫 Fragment Shader(片斷着色器),除此以外你可能還須要一點點圖像處理相關的知識。下面我將嘗試經過 GPUImage 中的 GPUImageColorInvertFilter(反色濾鏡)來說解一下它的運做過程。git
先看.h 文件:github
#import "GPUImageFilter.h" @interface GPUImageColorInvertFilter : GPUImageFilter { } @end
很簡單,能夠看出 GPUImageColorInvertFilter 是繼承了 GPUImageFilter算法
而後看 .m 文件 中 @implementation 以前的一段代碼框架
NSString *const kGPUImageInvertFragmentShaderString = SHADER_STRING ( varying highp vec2 textureCoordinate; uniform sampler2D inputImageTexture; void main() { lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); gl_FragColor = vec4((1.0 - textureColor.rgb), textureColor.a); } );
第 1 行,能夠看到 SHADER_STRING
宏中包含着咱們的 Shader (着色器)代碼,咱們的着色器字符串賦給一個 const NSString 對象(這個常量將在 GPUImageFilter 及其子類的初始化過程當中用來設置 filter)。函數
第 二、3 行聲明瞭兩個變量。ui
varying
變量是Vertex 和 Fragment Shader(頂點着色器和片斷着色器)之間作數據傳遞用的,通常 Vertex Shader(頂點着色器) 修改 varying 變量的值,而後 Fragment Shader(片斷着色器)使用該varying變量的值。所以varying 變量在 Vertex 和 Fragment Shader 中聲明必須一致。放到這裏,也就是說 textureCoordinate
必須叫這個名字不能改。3d
highp
聲明 textureCoordinate
精度(相應的還有mediump
和lowp
)。code
vec2
聲明textureCoordinate
是一個二維向量。orm
uniform
聲明 inputImageTexture
是外部程序傳遞給 Shader 的變量, Shader 程序內部只能用,不能改。 sampler2D
聲明變量是一個2D紋理。
第 4 行,相信你並不陌生,沒錯兒 Shader 也是從 main() 函數開始執行的。
第 5 行,texture2D
紋理取樣器,根據紋理座標返回紋理單元的值。
第 6 行,(1.0 - textureColor.rgb)
去 textureColor
也就是原圖的 RGB 值,作了一個向量的減法,這是圖像的反色算法,而後把通過反色的 RGB 值和原圖的 Alpha 值組成一個新的 vec4(四維向量)值賦給 gl_FragColor
。 gl_FragColor
是 Fragment Shader 預先定義的變量,賦給它的值就是該片斷最終的顏色值。
Shader 到這裏已經解釋完了,可能你依然雲裏霧裏,我來講一下我對這部分功能的理解,可能不對,但目前是管用的,方便你理解:GPUImage 中應該有一個 Vertex Shader,它對圖像逐個像素掃描,經過 textureCoordinate
變量將當前的掃描座標傳遞給咱們的 Fragment Shader,inputImageTexture
包含咱們要處理的圖像的所有信息,在 Shader 程序內部經過 texture2D
獲得 inputImageTexture
在當前位置 textureCoordinate
的 RGBA 值,運用圖像處理知識,算出想要的新的 RGBA 值,把結果值賦給 gl_FragColor
就算完成了。
如今咱們繼續看代碼,在 Shader 以後是 GPUImageColorInvertFilter 的實現:
@implementation GPUImageColorInvertFilter - (id)init; { if (!(self = [super initWithFragmentShaderFromString:kGPUImageInvertFragmentShaderString])) { return nil; } return self; } @end
很簡單,就是使用剛纔的着色器代碼來設置 filter。這樣一個新的濾鏡就誕生了~
網路上關於 GPUImage 自定義濾鏡 和 GLSL 的資料不是特別多,我斗膽把本身摸索到的理解在這裏和你分享,但願對你有所幫助,若有錯誤指出歡迎指出,另外,能夠去這裏查閱 OpenGL GLSL 文檔,玩的愉快 (●°u°●) 」
from : http://www.itiger.me/?p=143&utm_source=tuicool