UE4 描边

Posted on   |     Views

前言

不管在 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 到场景中,如图

打开这个 PostProcessVolumeUnbound 属性,否则只有当摄像机处在这个 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,来计算乘积,有 9Scalar 深度值输入,和 3Vector3 输入用来表示 3 x 3Sobel Operator 矩阵,输入材质函数如图所示

描边后处理材质

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

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

最终效果

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

描边抖动

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

参考文档