UE4 描边

前言

不管在 RTS 或者 FPS 类型的游戏中,描边都是一个基础的功能。在 RTS 游戏中,对单位描边一般用来表示选中这个单位或者鼠标悬浮在这个单位上。在 FPS 游戏中,描边一般用在被建筑物遮挡的单位上,描述这个单位被遮挡部分的轮廓。

Depth Map

Depth Map 描述的是场景中的物体和摄像机之间的距离,距离越近,值越小,颜色越深。可以在显示模式中切换成 Scene Depth 来查看深度显示模式,如图

1 Open Scene Depth.png

正常的场景

2 Scene Lit.png

按深度显示的场景

3 Scene Depth.png

Custom Depth Map

在游戏中,我们需要动态的显示/隐藏单位的描边,所以就要使用到自定义深度图(Custom Depth)来完成这个功能,因为 Custom Depth 只会渲染 Render CustomDepth Pass 属性为 True 的单位,所以我们可以通过控制这个单位的 SkeletalMeshComponent 中的 bRenderCustomDepth 属性来控制描边,如下图所示,只有一个单位渲染到 Custom Depth

4 Custom Depth.png

PostProcessVolume

要实现描边的功能,基本步骤是实现一个后处理描边材质,创建一个 PostProcessVolume,将后处理材质应用到这个 Volume中,打开要描边的单位的 Render CustomDepth Pass 属性。

6 Render CustomDepth Pass.png
首先拖动一个 PostProcessVolume 到场景中,如图

5 Create PostProcessVolume.png

打开这个 PostProcessVolumeUnbound 属性,否则只有当摄像机处在这个 Volume 中的时候后处理材质才生效,如图

7 Open Unbound.png

后处理材质

首先,创建一个材质,并修改这个材质为后处理材质,如图

8 Create PostProcess Materail.png

示例:实现显示模式中的 Custom Depth 效果

9 Custom Depth PP Material.png

将这个材质应用到 PostProcessVolume 中,如图

10 Apply PP Materail.png

最终效果如图

11 Custom Depth Demo.png

为什么材质中要除以 5000

因为 SceneTexture 中的 CustomDepth 通道表示像素和摄像机之间的距离,这个值相对于颜色的范围区间 [0, 1] 显得非常大,所以要对这个值进行处理,使距离值落在 [0, 1] 之间,否则这个后处理材质只会得到一个全白的结果

描边材质

描边材质的核心功能就是检测物体边缘,而检测物体边缘有很多种方法,本文中使用 Sobel Operator 算法来进行检测

Sobel Operator 简述

对图片中的每一个像素,将其和其周围的八个像素值依次和 Sobel Operator 相乘,得到的结果值为这个像素的相对值,如图所示

12 sobelEffect.png

Sobel Operator 分为水平和垂直两个方向,所以需要对每一个像素都执行水平和垂直两个方向的计算,再将得到的两个结果按照以下公式计算出最终的结果

13 CombineSobel.gif

Sobel Operator 两个方向的矩阵如下

14 Sobel Gx.png

15 Sobel Gy.png

根据和当前像素的偏移量来计算深度值

创建一个 Material Function MF_ExtraceDepth,有一个输入,为 Vector2,一个输出,为深度值,材质函数如图所示

16 MF_ExtractDepth_new.png

计算九个深度值和Sobel算子的乘积

创建另一个材质函数 MF_ConvolveTexture,来计算乘积,有 9Scalar 深度值输入,和 3Vector3 输入用来表示 3 x 3Sobel Operator 矩阵,输入材质函数如图所示

17 MF_ConvolveTexture.png

描边后处理材质

打开之前创建的后处理材质,调用 MF_ExtraceDepthMF_ConvolveTexture 材质函数计算 GxGy,如图

18 Get Gx and Gy.png

最终从 GxGy 两个分量计算最终的深度相对值,并将结果和阈值进行对比,大于阈值就输出描边颜色,如图

19 Outline Color.png

最终效果

如图所示,打开 Render CustomDepth 属性后,单位就会被描边

20 Last Result.png

描边抖动

在游戏中查看效果,会发现描边一直在抖动,根据文档 Temporal Anti-Aliasing or Why the GBuffer Jitters,解决方法如下

21 fix jitter.png

参考文档