前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【iOS】(一)GPUImage的结构,滤镜链的实现原理

【iOS】(一)GPUImage的结构,滤镜链的实现原理

作者头像
MapleYe
发布2020-03-31 12:37:28
2.3K0
发布2020-03-31 12:37:28
举报
文章被收录于专栏:MapleYeMapleYe

前言

学了OpenGL,OpenGLES后,去阅读了GPUImage的源码,使用了一段时间,接下来,记录一下我对GPUImage使用和源码阅读的一些分析吧。 相关引用 从0打造一个GPUImage(6)-GPUImage的多滤镜处理逻辑

GPUImage结构

GPUImage目录.png

对于GPUImage,可以分为

  • GLProgram 用于加载shader,链接program的类
  • GPUImageContext 用于OpenGLContext上下文管理的
  • GPUImageFrameBuffer 用于frameBuffer的管理,GPUImage的滤镜链靠的就是传递GPUImageFrameBuffer
  • GPUImageFrameBufferCache 用于缓存frameBuffer的类,会根据texture的option属性,已经size生成key,作为缓存
  • Sources 可以理解为万恶之源吧,所有的渲染处理,都是从这里开始的,必须继承GPUImageOutput
  • Filter 滤镜类 既继承了GPUImageOutput,也遵守GPUImageInput的类,从而实现GPUImageOutput -> filter -> filter -> GPUImageInput的滤镜链的关键
  • Outputs,实现了GPUImageInput的组件,是渲染结果的终点

GPUImage的滤镜链

上面也提了,所谓的GPUImage滤镜链就是 GPUImageOutput -> filter -> filter -> GPUImageInput GPUImageOutput通过target数组(里面都是实现GPUImageInput组件),组成了滤镜链的关系,我们需要牢牢的记住这个滤镜链的关系,这样开发的时候,我们就知道如何Debug,如何实现我们需要的效果。那么问题来了,为什么GPUImage可以实现这样的滤镜链呢?

滤镜链实现的原理

这里我们先抛开GPUImage,用OpenGL ES去实现一个具有滤镜叠加效果的Demo,这里的Demo我是参考叶孤城的这篇文章,从0打造一个GPUImage(6)-GPUImage的多滤镜处理逻辑

Demo需要实现的效果,是将一张图片,先后通过叠加亮度滤镜饱和度滤镜最后显示在屏幕上。

使用GPUImage的渲染步骤

  • 通过GPUImagePicture加载图片(这里就是source)
  • source addTarget亮度滤镜
  • 亮度滤镜传递渲染结果给饱和度滤镜
  • 饱和度滤镜传递给GPUImageView,GPUImageView显示渲染结果,

使用OpenGLES的渲染步骤

那么对应的OpenGLES,我们会怎么做呢?首先我们需要以下东西

  • 一个源,其实就是将图片信息加载为纹理的过程,这里对应GPUImagePicture
  • 3个frameBuffer,前两个挂载亮度滤镜饱和度滤镜texture,通过glFramebufferTexture2D绑定texture到frameBuffer上,最后一个frameBuffer挂载的是renderBuffer用于显示
代码语言:javascript
复制
// 绑定texture
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, brightnessTexture, 0)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, saturationTexture, 0)
// 绑定renderBuffer
 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderBuffer);
  • 3个Program,前两个Program用于加载亮度滤镜饱和度滤镜的frameShader文件(这里就相当于GPUImageInput),最后一个Program加载的frameShader只需要把rgb信息从纹理中取出,然后展示就行了(这里就相当于GPUImageView)。

从以上的步骤,我们可以总结以下结论

  • 1、源总是会产生texture开始传递的,这里其实就是GPUImageOutput的职责
  • 2、每个滤镜Filter都是通过传递frameBuffer挂载texture来传递渲染结果的(这里的滤镜对应一个program,一个frameBuffer)
  • 3、对于需要显示的渲染结果的GPUImageInput,例如GPUImageView,需要依赖frameBuffer挂载renderBuffer进行显示

对于这个Demo的一个流程图,可以参考从0打造一个GPUImage(6)-GPUImage的多滤镜处理逻辑的一幅图,Demo的详细实现请看原文吧。

OpenGLES滤镜叠加流程图

总结

以上就是GPUImage对于滤镜链的实现原理,只有你懂了OpenGL ES的渲染流程,才能彻底的明白GPUImage的滤镜链的原理。所以时时刻刻记住以下关系 GPUImageOutput -> filter -> filter -> GPUImageInput 当然也可以存在多个Source,多个Input的情况,例如要给一个视频添加水印,用GPUImageMovie用于输出视频纹理,用GPUImageUIElement输出UI空间的纹理,通过一个filter进行Blend,最后用一个GPUImageView进行预览,用GPUImageMovieWriter进行输出,滤镜链关系如下

代码语言:javascript
复制
GPUImageOutput -> filter -> filter -> GPUImageInput
                    ↑         ↓
GPUImageOutput ----->    GPUImageInput
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • GPUImage结构
  • GPUImage的滤镜链
    • 滤镜链实现的原理
      • 使用GPUImage的渲染步骤
      • 使用OpenGLES的渲染步骤
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档