滤镜特效节点开发
1. 概述
XImageEffect库是一个图像处理框架,允许定义前处理和后处理逻辑,前处理是对背景图像(如摄像头采集的图像)所做的处理,后处理是对背景图像与3D引擎渲染内容合成的结果所做的处理。XImageEffect作为滤镜框架,允许用户在该框架下创建自定义滤镜。
一个滤镜效果对应一个滤镜节点,多个滤镜节点构成一张图(这张图可以是一个滤镜链),每个滤镜节点有确定的输入和输出(可以有多个输入和输出),因此滤镜节点构成的图是一张有向图。滤镜处理器在执行滤镜效果的时候,即是对这张有向图进行遍历,依次执行每一个滤镜节点。
滤镜通过材质的方式来定义,创建一个滤镜即是创建一个材质。材质是渲染引擎的概念,一个材质描述一种表现效果,从技术细节上来讲,材质封装了一套渲染状态、shader代码及参数。更复杂的滤镜可以由lua脚本来控制逻辑(比如更新VertexBuffer),lua脚本以及前面提到的材质文件、shader代码都可以看做资源文件,支持热更新。
2. 示例
下面以一个示例(AR背景层特效)来讲解在XImageEffect框架下编写滤镜的方法。该示例实现如下效果。
滤镜编写流程整体分为三个步骤:
- 编写材质文件,以.mt为后缀。
- 编写shader文件,包括vertex shader和pixel shader文件,以.glsl为后缀。
- 创建XImageEffectNode,并构建XImageEffectGraph。
3. 编写材质文件
材质文件的后缀名为.mt,以文本形式编辑。以AR背景层特效为例,ar_background.mt的定义如下图所示。
- MaterialProperties:材质属性,该部分定义渲染状态、shader文件名等。
- AlphaType:混合模式,可取值为Opaque、Translucent。
- pass:定义一个渲染通道,渲染顺序与pass定义顺序一致。
- SrcColorBlend:源颜色混合系数。可取值为One、zero、SrcAlpha、InvSrcAlpha、SrcColor、InvSrcColor。
- DestColorBlend:目的颜色混合系数。可取值同SrcColorBlend。
- SrcColorBlend和DestColorBlend共同决定源颜色如何与目标颜色如何混合,假设SrcColor和DestColor分别表示源颜色和目标颜色,混合公式为:FinalColor = SrcColor * SrcColorBlend+DestColor * DestColorBlend。
- 最常用的组合为:SrcColorBlend为One,DestColorBlend为Zero,表示源颜色直接覆盖目标颜色,等效于将混合模式设置为Opaque;SrcColorBlend为SrcAlpha,DestColorBlend为InvSrcAlpha,表示源颜色按照alpha值与目标颜色混合,即alpha半透明。
- VertexShader:顶点着色器文件名。
- PixelShader:片段着色器文件名。
- VSEntry:顶点着色器函数入口,默认为main。
- PSEntry:片段着色器函数入口,默认为main。
- CullMode:裁剪模式,可取值为Back、Front或Off,分别表示背面剔除、正面剔除和关闭剔除。
- ClearColor:清屏颜色。
- Input:输入纹理名。
- “InputTextureSampler”为系统内置输入,表示节点默认输入(背景纹理),即当前帧。
- 当输入纹理名不为“InputTextureSampler”时,表示其他pass的临时输出。
- @Point为纹理过滤模式。其他可取值为@Bilinear、@Trilinear、@Anisotropic。
- @ClampU和@ClampV表示寻址模式。其他可取值为@WrapU、@WrapV、@MirrorU、@MirrorV、@BorderU、@BorderV。
- 寻址模式对应OpenGL中纹理寻址的WrapMode。@WrapU和@WrapV对应GL_REPEAT,@MirrorU和@MirrorV对应GL_MIRRORED_REPEAT,@ClampU、@ClampV、@BorderU和@BorderV均对应GL_CLAMP_TO_EDGE。最常用的是@ClampU和@ClampV。具体细节可参考OpenGL纹理相关文档。
- Output:输出渲染缓冲名。
- “OutputRenderTarget”为系统内置输出,表示节点默认输出(图像处理结果)。
- 当输出缓冲不为“OutputRenderTarget”时,可以设置其格式和大小。
- @RGBA表示渲染缓冲的格式为R8G8B8A8。其他可取值为@RGB、@Luminance、@LuminanceAlpha。注:@Luminance和@LuminanceAlpha在安卓平台有问题,暂时别用。
- @Relative_0.25_0.25表示渲染缓冲的大小是相对尺寸,宽和高都是输出纹理的0.25倍。Relative表示尺寸为相对模式,Absolute表示尺寸为绝对模式。例如,@Absolute_256_256表示渲染缓冲的尺寸为256x256。
- MaterialUserParameters:用户材质参数,shader的参数定在在这。可选参数类型为float、float2、float3、float4、matrix4、texture2D、textureCube。
- FrameCache模块说明(允许设置输入图像的像素缓存)
- 添加XImageEffectNodeFrameCache类型,提供缓存帧的功能,可以在ImageEffectGraph内任意位置插入XImageEffectNodeFrameCache节点(一个Graph中可以插入多个FrameCache节点)。
- 支持自动触发cache和手动触发cache,手动触发时可以通过CacheFrame接口传入帧的标签,在shader中可以通过该标签拿到缓存帧。
- FrameCache_xxx_yyy是关键字,shader中可以通过该关键字拿到某个被cache的帧。xxx是FrameCache节点的名字,yyy是数字或者手动触发时的标签(如果是数字,表示倒数第几帧,通常用于延迟滤镜)。
- XProject中的demo01有相关用法演示。
- 之前,缓存帧的shader关键字是InputTextureSampler_n,现在需要相应的改为FrameCache_xxx_n,不兼容之前的关键字。
- XImageEffectNodeUser节点支持多输入多输出,最多支持7个输入和7个输出。
- InputTextureSampler_n是输入关键字,n取0-6。
- OutputRenderTarget_n是输出关键字,n取0-6。
- 之前的关键字InputTextureSampler和OutputRenderTarget可兼容,InputTextureSampler被解释为InputTextureSampler_0,OutputRenderTarget被解释为OutputRenderTarget_0。
4. 编写Shader文件
Shader文件有两项注意事项:
- Shader文件需要进行转码加密。(XImageEffect库中g_pXImageEffectShaderCodec提供了转解码接口)。
- Shader文件必须与其材质文件(.mt文件)在同一级目录下。如下图所示。
5. 创建特效节点
图像处理由一张图(XImageEffectGraph)表示,图中的每个节点(XImageEffectNode)表示一个具体的图像处理效果。
用户通过材质和shader编写的特效均是通过XImageEffectNodeUser类型的节点来实现的,该节点接受一个材质实例作为输入,由材质定义的滤镜效果最终通过该节点类型的对象来执行。
图的构建是由用户来完成的,用户定义一个XImageEffectGraphBuilder的子类,实现其BuildImageEffectGraph接口。以AR背景层特效实例为例,图的结构如下图所示。
编辑器工具
魔方编辑器提供了编写图像特效的工具,可以在编辑器中创建滤镜Actor、自定义滤镜链、编辑mt文件、编写shader等。 编辑器使用方式可参考