回顧
-
GPUImageFilter就是用來(lái)接收源圖像,通過(guò)自定義的頂點(diǎn)、片元著色器來(lái)渲染新的圖像,并在繪制完成后通知響應(yīng)鏈的下一個(gè)對(duì)象。 -
GPUImageFramebuffer就是用來(lái)管理紋理緩存的格式與讀寫(xiě)幀緩存的buffer。 -
GPUImageVideoCamera是GPUImageOutput的子類(lèi),提供來(lái)自攝像頭的圖像數(shù)據(jù)作為源數(shù)據(jù),一般是響應(yīng)鏈的源頭。 -
GPUImageView是響應(yīng)鏈的終點(diǎn),一般用于顯示GPUImage的圖像。
琨君的基于GPUImage的實(shí)時(shí)美顏濾鏡對(duì)GPUImage實(shí)現(xiàn)美顏濾鏡的原理和思路做了詳細(xì)介紹。
本文以琨君的代碼為demo,結(jié)合前兩篇解析,探究美顏過(guò)程中的GPUImage實(shí)現(xiàn)。
GPUImage類(lèi)介紹
1、GPUImageFilterGroup
GPUImageFilterGroup是多個(gè)filter的集合,terminalFilter為最終的filter,initialFilters為filter數(shù)組。GPUImageFilterGroup本身不繪制圖像,對(duì)GPUImageFilterGroup添加刪除Target操作的操作都會(huì)轉(zhuǎn)為terminalFilter的操作。
2、GPUImageTwoInputFilter
GPUImageTwoInputFilter是GPUImageFilter的子類(lèi),對(duì)兩個(gè)輸入紋理進(jìn)行通用的處理,需要繼承它并準(zhǔn)備自己的片元著色器。
兩個(gè)輸入紋理默認(rèn)為inputImageTexture和inputImageTexture2。
- 重寫(xiě)了下面的函數(shù),修改
GPUImageFilter繪制的邏輯。
- (void)renderToTextureWithVertices:(const GLfloat *)vertices
textureCoordinates:(const GLfloat *)textureCoordinates;
下面這部分是核心的繪制邏輯:
glActiveTexture()是選擇紋理單元,glBindTexture()是把紋理單元和firstInputFramebuffer、secondInputFramebuffer管理的紋理內(nèi)存綁定。glUniform1i()告訴GLSL選擇的紋理單元是2。
這部分在上一篇介紹也有提到,再詳細(xì)闡述:glActiveTexture()選擇的是紋理單元,和glGenTextures()返回的數(shù)字沒(méi)有關(guān)系,可以在紋理單元2上面綁定紋理12。
glGenTextures()返回的紋理可以是GL_TEXTURE_2D類(lèi)型也可以是GL_TEXTURE_CUBE_MAP類(lèi)型,取決于glBindTexture()第一次綁定紋理的是GL_TEXTURE_2D還是GL_TEXTURE_CUBE_MAP。
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, [firstInputFramebuffer texture]);
glUniform1i(filterInputTextureUniform, 2);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, [secondInputFramebuffer texture]);
glUniform1i(filterInputTextureUniform2, 3);
-
nextAvailableTextureIndex用于獲取下一個(gè)紋理索引
- (NSInteger)nextAvailableTextureIndex;
{
if (hasSetFirstTexture)
{
return 1;
}
else
{
return 0;
}
}
setInputFramebuffer: atIndex:會(huì)根據(jù)上面獲取的textureIndex設(shè)置firstInputFramebuffer和secondInputFramebuffer。如果是textureIndex = 0,設(shè)置hasSetFirstTexture表示已經(jīng)設(shè)置第一個(gè)紋理。
3、GPUImageThreeInputFilter
GPUImageThreeInputFilter的邏輯與GPUImageTwoInputFilter類(lèi)似,增加了thirdInputFramebuffer作為第三個(gè)紋理inputImageTexture3的輸入。
4、GPUImageBeautifyFilter
GPUImageBeautifyFilter是基于GPUImage的實(shí)時(shí)美顏濾鏡中的美顏濾鏡,包括GPUImageBilateralFilter、GPUImageCannyEdgeDetectionFilter、GPUImageCombinationFilter、GPUImageHSBFilter。
繪制流程

1、
GPUImageVideoCamera捕獲攝像頭圖像
調(diào)用newFrameReadyAtTime: atIndex:通知GPUImageBeautifyFilter;2、
GPUImageBeautifyFilter調(diào)用newFrameReadyAtTime: atIndex:
通知GPUImageBilateralFliter輸入紋理已經(jīng)準(zhǔn)備好;3、
GPUImageBilateralFliter繪制圖像后在informTargetsAboutNewFrameAtTime(),
調(diào)用setInputFramebufferForTarget: atIndex:
把繪制的圖像設(shè)置為GPUImageCombinationFilter輸入紋理,
并通知GPUImageCombinationFilter紋理已經(jīng)繪制完畢;4、
GPUImageBeautifyFilter調(diào)用newFrameReadyAtTime: atIndex:
通知GPUImageCannyEdgeDetectionFilter輸入紋理已經(jīng)準(zhǔn)備好;5、同3,
GPUImageCannyEdgeDetectionFilter繪制圖像后,
把圖像設(shè)置為GPUImageCombinationFilter輸入紋理;6、
GPUImageBeautifyFilter調(diào)用newFrameReadyAtTime: atIndex:
通知GPUImageCombinationFilter輸入紋理已經(jīng)準(zhǔn)備好;7、
GPUImageCombinationFilter判斷是否有三個(gè)紋理,三個(gè)紋理都已經(jīng)準(zhǔn)備好后
調(diào)用GPUImageThreeInputFilter的繪制函數(shù)renderToTextureWithVertices: textureCoordinates:,
圖像繪制完后,把圖像設(shè)置為GPUImageHSBFilter的輸入紋理,
通知GPUImageHSBFilter紋理已經(jīng)繪制完畢;8、
GPUImageHSBFilter調(diào)用renderToTextureWithVertices: textureCoordinates:繪制圖像,
完成后把圖像設(shè)置為GPUImageView的輸入紋理,并通知GPUImageView輸入紋理已經(jīng)繪制完畢;9、
GPUImageView把輸入紋理繪制到自己的幀緩存,然后通過(guò)
[self.context presentRenderbuffer:GL_RENDERBUFFER];顯示到UIView上。
總結(jié)
GPUImageFilter
GPUImageFramebuffer
GPUImageVideoCamera
GPUImageView
GPUImageFilterGroup
GPUImageTwoInputFilter
GPUImageThreeInputFilter
這是學(xué)習(xí)這個(gè)demo需要了解的7個(gè)類(lèi)。
在繪制流程圖的過(guò)程中,對(duì)GPUImage的響應(yīng)鏈有了更清晰的認(rèn)識(shí)。