美文网首页Graphics
GPUImage-实时美颜滤镜

GPUImage-实时美颜滤镜

作者: 辉辉岁月 | 来源:发表于2021-11-25 16:40 被阅读0次

    GPUImage类介绍

    • GPUImageFilter就是用来接收源图像,通过自定义的顶点、片元着色器来渲染新的图像,并在绘制完成后通知响应链的下一个对象。
    • GPUImageFramebuffer就是用来管理纹理缓存的格式与读写帧缓存的buffer。
    • GPUImageVideoCameraGPUImageOutput的子类,提供来自摄像头的图像数据作为源数据,一般是响应链的源头。
    • GPUImageView是响应链的终点,一般用于显示GPUImage的图像。

    琨君基于GPUImage的实时美颜滤镜对GPUImage实现美颜滤镜的原理和思路做了详细介绍。
    本文以琨君的代码为demo,结合前两篇解析,探究美颜过程中的GPUImage实现。

    1、GPUImageFilterGroup

    GPUImageFilterGroup是多个filter的集合,terminalFilter为最终的filter,initialFilters为filter数组。GPUImageFilterGroup本身不绘制图像,对GPUImageFilterGroup添加删除Target操作的操作都会转为terminalFilter的操作。

    2、GPUImageTwoInputFilter

    GPUImageTwoInputFilterGPUImageFilter的子类,对两个输入纹理进行通用的处理,需要继承它并准备自己的片元着色器。
    两个输入纹理默认为inputImageTextureinputImageTexture2

    • 重写了下面的函数,修改GPUImageFilter绘制的逻辑。
    - (void)renderToTextureWithVertices:(const GLfloat *)vertices
     textureCoordinates:(const GLfloat *)textureCoordinates;
    
    

    下面这部分是核心的绘制逻辑:
    glActiveTexture()是选择纹理单元,glBindTexture()是把纹理单元和firstInputFramebuffersecondInputFramebuffer管理的纹理内存绑定。glUniform1i()告诉GLSL选择的纹理单元是2。
    这部分在上一篇介绍也有提到,再详细阐述:glActiveTexture()选择的是纹理单元,和glGenTextures()返回的数字没有关系,可以在纹理单元2上面绑定纹理12。
    glGenTextures()返回的纹理可以是GL_TEXTURE_2D类型也可以是GL_TEXTURE_CUBE_MAP类型,取决于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用于获取下一个纹理索引
    - (NSInteger)nextAvailableTextureIndex;
    {
        if (hasSetFirstTexture)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
    
    

    setInputFramebuffer: atIndex:会根据上面获取的textureIndex设置firstInputFramebuffersecondInputFramebuffer。如果是textureIndex = 0,设置hasSetFirstTexture表示已经设置第一个纹理。

    3、GPUImageThreeInputFilter

    GPUImageThreeInputFilter的逻辑与GPUImageTwoInputFilter类似,增加了thirdInputFramebuffer作为第三个纹理inputImageTexture3的输入。

    4、GPUImageBeautifyFilter

    GPUImageBeautifyFilter基于GPUImage的实时美颜滤镜中的美颜滤镜,包括GPUImageBilateralFilterGPUImageCannyEdgeDetectionFilterGPUImageCombinationFilterGPUImageHSBFilter

    绘制流程

    • 1、GPUImageVideoCamera捕获摄像头图像
      调用newFrameReadyAtTime: atIndex:通知GPUImageBeautifyFilter

    • 2、GPUImageBeautifyFilter调用newFrameReadyAtTime: atIndex:
      通知GPUImageBilateralFliter输入纹理已经准备好;

    • 3、GPUImageBilateralFliter 绘制图像后在informTargetsAboutNewFrameAtTime()
      调用setInputFramebufferForTarget: atIndex:
      把绘制的图像设置为GPUImageCombinationFilter输入纹理,
      并通知GPUImageCombinationFilter纹理已经绘制完毕;

    • 4、GPUImageBeautifyFilter调用newFrameReadyAtTime: atIndex:
      通知 GPUImageCannyEdgeDetectionFilter输入纹理已经准备好;

    • 5、同3,GPUImageCannyEdgeDetectionFilter 绘制图像后,
      把图像设置为GPUImageCombinationFilter输入纹理;

    • 6、GPUImageBeautifyFilter调用newFrameReadyAtTime: atIndex:
      通知 GPUImageCombinationFilter输入纹理已经准备好;

    • 7、GPUImageCombinationFilter判断是否有三个纹理,三个纹理都已经准备好后
      调用GPUImageThreeInputFilter的绘制函数renderToTextureWithVertices: textureCoordinates:
      图像绘制完后,把图像设置为GPUImageHSBFilter的输入纹理,
      通知GPUImageHSBFilter纹理已经绘制完毕;

    • 8、GPUImageHSBFilter调用renderToTextureWithVertices: textureCoordinates:绘制图像,
      完成后把图像设置为GPUImageView的输入纹理,并通知GPUImageView输入纹理已经绘制完毕;

    • 9、GPUImageView把输入纹理绘制到自己的帧缓存,然后通过
      [self.context presentRenderbuffer:GL_RENDERBUFFER];显示到UIView上。

    总结

    GPUImageFilter
    GPUImageFramebuffer
    GPUImageVideoCamera
    GPUImageView
    GPUImageFilterGroup
    GPUImageTwoInputFilter
    GPUImageThreeInputFilter
    这是学习这个demo需要了解的7个类。
    在绘制流程图的过程中,对GPUImage的响应链有了更清晰的认识。

    相关文章

      网友评论

        本文标题:GPUImage-实时美颜滤镜

        本文链接:https://www.haomeiwen.com/subject/jmtztrtx.html