UE4 描边
前言
- 本文引擎版本:
4.15
- 项目源码地址
不管在 RTS
或者 FPS
类型的游戏中,描边都是一个基础的功能。在 RTS
游戏中,对单位描边一般用来表示选中这个单位或者鼠标悬浮在这个单位上。在 FPS
游戏中,描边一般用在被建筑物遮挡的单位上,描述这个单位被遮挡部分的轮廓。
Depth Map
Depth Map
描述的是场景中的物体和摄像机之间的距离,距离越近,值越小,颜色越深。可以在显示模式中切换成 Scene Depth
来查看深度显示模式,如图
正常的场景
按深度显示的场景
Custom Depth Map
在游戏中,我们需要动态的显示/隐藏单位的描边,所以就要使用到自定义深度图(Custom Depth
)来完成这个功能,因为 Custom Depth
只会渲染 Render CustomDepth Pass
属性为 True
的单位,所以我们可以通过控制这个单位的 SkeletalMeshComponent
中的 bRenderCustomDepth
属性来控制描边,如下图所示,只有一个单位渲染到 Custom Depth
中
PostProcessVolume
要实现描边的功能,基本步骤是实现一个后处理描边材质,创建一个 PostProcessVolume
,将后处理材质应用到这个 Volume
中,打开要描边的单位的 Render CustomDepth Pass
属性。
首先拖动一个 PostProcessVolume
到场景中,如图
打开这个 PostProcessVolume
的 Unbound
属性,否则只有当摄像机处在这个 Volume
中的时候后处理材质才生效,如图
后处理材质
首先,创建一个材质,并修改这个材质为后处理材质,如图
示例:实现显示模式中的 Custom Depth
效果
将这个材质应用到 PostProcessVolume
中,如图
最终效果如图
为什么材质中要除以 5000
因为 SceneTexture
中的 CustomDepth
通道表示像素和摄像机之间的距离,这个值相对于颜色的范围区间 [0, 1]
显得非常大,所以要对这个值进行处理,使距离值落在 [0, 1]
之间,否则这个后处理材质只会得到一个全白的结果
描边材质
描边材质的核心功能就是检测物体边缘,而检测物体边缘有很多种方法,本文中使用 Sobel Operator 算法来进行检测
Sobel Operator 简述
对图片中的每一个像素,将其和其周围的八个像素值依次和 Sobel Operator
相乘,得到的结果值为这个像素的相对值,如图所示
Sobel Operator
分为水平和垂直两个方向,所以需要对每一个像素都执行水平和垂直两个方向的计算,再将得到的两个结果按照以下公式计算出最终的结果
Sobel Operator
两个方向的矩阵如下
根据和当前像素的偏移量来计算深度值
创建一个 Material Function
MF_ExtraceDepth
,有一个输入,为 Vector2
,一个输出,为深度值,材质函数如图所示
计算九个深度值和Sobel算子的乘积
创建另一个材质函数 MF_ConvolveTexture
,来计算乘积,有 9
个 Scalar
深度值输入,和 3
个 Vector3
输入用来表示 3 x 3
的 Sobel Operator
矩阵,输入材质函数如图所示
描边后处理材质
打开之前创建的后处理材质,调用 MF_ExtraceDepth
和 MF_ConvolveTexture
材质函数计算 Gx
和 Gy
,如图
最终从 Gx
和 Gy
两个分量计算最终的深度相对值,并将结果和阈值进行对比,大于阈值就输出描边颜色,如图
最终效果
如图所示,打开 Render CustomDepth
属性后,单位就会被描边
描边抖动
在游戏中查看效果,会发现描边一直在抖动,根据文档 Temporal Anti-Aliasing or Why the GBuffer Jitters ,解决方法如下