GPUImage详细解析(三)- 实时美颜滤镜

回顾

解析(一) 解析(二)

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

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

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的响应链有了更清晰的认识。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python小屋

Python绘制渐变色三角形

本文要点在于Python扩展库pyopengl的应用,关于OpenGL函数参数含义可以查阅有关资料。 import sys from OpenGL.GL imp...

40760
来自专栏落影的专栏

OpenGL ES学习阶段性总结

前言 最近观看下面这本书有感,结合之前的学习,对OpenGL的知识进行回顾。 ? 概念 帧缓存:接收渲染结果的缓冲区,为GPU指定存储渲染结果的区域。 ...

44380
来自专栏Deep learning进阶路

caffe随记(二) --- 数据结构简介

caffe随记(二) --- 数据结构简介 注:这篇文章博文我写的内容有点多,建议看一下左上角的目录,对本文结构有个大致了解。 1、Blob Blob其实...

27400
来自专栏Python小屋

Python绘制三次贝塞尔曲线

对于贝塞尔曲线而言,其特点在于第一个控制点恰好是曲线的起点,最后一个控制点是曲线的终点,其他控制点并不在曲线上,而是起到控制曲线形状的作用。另外,曲线的起点处与...

71860
来自专栏章鱼的慢慢技术路

OpenGL基本框架与三维对象绘制

17220
来自专栏郭艺帆的专栏

庖丁解牛:GIF

GIF 是一种使用 LZW 压缩,支持多张图像的容器。支持256色,透明通道为1bit。作为互联网表情包的载体,GIF 这项80年代的技术依然生生不息。

28900
来自专栏FreeBuf

中文点选验证码之自动识别

某次测试中遇到了汉字点选的验证码,看着很简单,尝试了一下发现有两种简单的识别方法,终于有空给重新整理一下,分享出来。

1.3K40
来自专栏PPV课数据科学社区

TensorFlow 数据集和估算器介绍

TensorFlow 1.3 引入了两个重要功能,您应当尝试一下: 数据集:一种创建输入管道(即,将数据读入您的程序)的全新方式。 估算器:一种创建 Ten...

33190
来自专栏hotqin888的专栏

golang随机抽奖代码

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hotqin888/article/det...

37820
来自专栏菩提树下的杨过

Matplotlib新手上路(上)

matplotlib是python里用于绘图的专用包,功能十分强大。下面介绍一些最基本的用法: 一、最基本的划线 先来一个简单的示例,代码如下,已经加了注释: ...

312100

扫码关注云+社区

领取腾讯云代金券