GPUImage詳細(xì)解析(三)- 實(shí)時(shí)美顏濾鏡

回顧

解析(一)
解析(二)

  • GPUImageFilter就是用來(lái)接收源圖像,通過(guò)自定義的頂點(diǎn)、片元著色器來(lái)渲染新的圖像,并在繪制完成后通知響應(yīng)鏈的下一個(gè)對(duì)象。
  • GPUImageFramebuffer就是用來(lái)管理紋理緩存的格式與讀寫(xiě)幀緩存的buffer。
  • GPUImageVideoCameraGPUImageOutput的子類(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

GPUImageTwoInputFilterGPUImageFilter的子類(lèi),對(duì)兩個(gè)輸入紋理進(jìn)行通用的處理,需要繼承它并準(zhǔn)備自己的片元著色器。
兩個(gè)輸入紋理默認(rèn)為inputImageTextureinputImageTexture2

  • 重寫(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è)置firstInputFramebuffersecondInputFramebuffer。如果是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í)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容