虚幻引擎4-后处理扫描效果



这个周末,我在课间有一些空闲时间(请注意,在撰写本文时作者正在获得科学硕士学位) ,我决定通过发明这种后处理扫描效果来重新创建着色器。 我想象它在游戏中被用作一种距离扫描效果。 我们还使用一些简单的噪声失真来使效果看起来更有趣。

在本文中,我将告诉您如何在UE4上实现此效果。 您可以通过多种方式创建此效果。 我选择了其中一种方法。

您可以在新选项卡中打开图像以更高分辨率查看它们。

主要组成


此效果的主要思想是使用Sobel运算符创建场景渲染的版本,然后将其与基于SphereMask的常用场景渲染混合,我们将对其进行动画处理以创建扫描效果。

此效果包含3个主要成分:

  • SphereMask可伸缩字段
  • Sobel-Edge函数(由于它是一个单独的主题,因此我将不解释该函数的工作原理,但是我将参考我使用的代码)
  • 在世界网格上叠加投影的纹理

SphereMask可伸缩字段


这一部分是关于我们如何创建可伸缩的SphereMask。 为此,我们将蓝图的位置转移到材料参数集,然后按以下方式使用它



将“ 钳位”节点的结果连接到材质的发射输出,您将看到类似以下的内容



“ TexLoc”是一个矢量3 ,它确定球体源的位置,在我的情况下,它是从一组材料参数中读取的,因此可以从游戏本身中读取它,例如,以确定玩家的位置。

上面指定的节点参数集创建一个球面半径为1024个单位的字段。 我仅将其用于在预览窗口中显示结果。 如果您想了解有关使用远程功能的更多信息并了解如何使用它们,我强烈建议您访问Inigo Quilez网站

现在,我们将使用“ 时间”按设定的时间间隔缩放球体。



这将给我们以下结果



Frac (时间)基本上为我们提供了一个恒定的周期,持续到0-1.0-1.0-1。 我们将时间乘以0.25以控制缩放速度,然后将结果乘以球体的半径,这将导致半径从0更改为1024,并为我们提供了动画蒙版。

这是一个很好的结果,但这不是我们想要的效果。 我们需要一个缩放环。 使用简单的计算即可轻松完成。



这将为我们提供我们想要的,一个长环,并且可以控制良好的渐变衰落。



Edge_Mask块中的数学运算基本上选择了渐变蒙版中的位置,在这种情况下,值为0.5,并从当前位置以给定的宽度确定蒙版的边缘,这使我们能够获得一个环。 我不会讨论获取蒙版边缘的技术细节,很可能会在以下一篇文章中谈到这一点。

如您所见,无需标量参数即可完全控制环的宽度,并且如果我们愿意,甚至可以控制边缘的衰减,但是在这种情况下我们不需要这样做。

下一步是使用噪音创建一个有趣的戒指版本。

为此,我们将使用UE4中的Vector Noise节点。 您可以在此处阅读有关的内容,也可以使用包含世界对齐UV坐标的噪波纹理。

在我的着色器中,我在“ 矢量噪声” 节点的“ Cellnoise”中设置“ 功能”参数,可以随意尝试使用该参数的其他类型以获得自己独特的效果。



结果将如下所示



这是我们的着色器的第一步完成,然后我们将考虑Sobel-Edge函数的实现。

Sobel-Edge功能


此功能有许多不同的选项,其中一些比其他选项更优化,由于这是一个单独的主题,因此我将不解释其本质,但是使用关键字“ Sobel Edge”或“ Sobel Operator”进行常规Google搜索将为您提供许多选择。 或使用Gepard_vvk- 算法 中枢上的文章选择图像轮廓

Sobel运算符的主要思想是:我们获取场景的RenderTarget (假设它是一个纹理,其中包含您当前在视口中看到的内容),并将每个像素与周围的所有相邻像素进行比较。 接下来,我们比较亮度差异,如果差异超过某个阈值,则将其标记为边缘,在此过程中,我们获得了黑白RenderTarget纹理蒙版 ,其中在边缘上调整了蒙版。

下面的代码是RebelMoogle在Shadertoy网站上创建的Sobel运算符函数的简单示例(很可能该选项未完全优化,因此您可以尝试其他实现),我们将在UE4的材料中重新创建它。

void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord.xy / iResolution.xy; vec3 TL = texture(iChannel0, uv + vec2(-1, 1)/ iResolution.xy).rgb; vec3 TM = texture(iChannel0, uv + vec2(0, 1)/ iResolution.xy).rgb; vec3 TR = texture(iChannel0, uv + vec2(1, 1)/ iResolution.xy).rgb; vec3 ML = texture(iChannel0, uv + vec2(-1, 0)/ iResolution.xy).rgb; vec3 MR = texture(iChannel0, uv + vec2(1, 0)/ iResolution.xy).rgb; vec3 BL = texture(iChannel0, uv + vec2(-1, -1)/ iResolution.xy).rgb; vec3 BM = texture(iChannel0, uv + vec2(0, -1)/ iResolution.xy).rgb; vec3 BR = texture(iChannel0, uv + vec2(1, -1)/ iResolution.xy).rgb; vec3 GradX = -TL + TR - 2.0 * ML + 2.0 * MR - BL + BR; vec3 GradY = TL + 2.0 * TM + TR - BL - 2.0 * BM - BR; fragColor.r = length(vec2(GradX.r, GradY.r)); fragColor.g = length(vec2(GradX.g, GradY.g)); fragColor.b = length(vec2(GradX.b, GradY.b)); } 


在UE4中,它看起来像这样



关于该函数实现的简要说明-确保将SceneTexture节点配置为使用PostProcessInput0



两个Custom节点GradXGradY ,以类似的方式配置它们



GradX

 return -TL + TR - 2.0 * ML + 2.0 * MR - BL + BR; 

Grady

 return TL + 2.0 * TM + TR - BL - 2.0 * BM - BR; 

这不必在Custom中完成,我只是为了方便起见使用它,因为否则将有太多的节点并且会形成意大利面条。

如果将函数结果插入发光材料输出中,则会看到以下内容



我们还将结果乘以常规vector3来制作所需颜色的边缘。



结果,边缘的颜色改变。



网格纹理叠加世界


最简单的部分:我们仅使用网格纹理并将其投影到世界各地,然后将其与Sobel-Edge函数结合使用即可获得炫酷效果。



如果将函数的结果连接到发射输出,您将看到



全部放在一起


现在,我们将所有三个部分放在一起以提高后期效果!

首先,我们结合Sobel-Edge和World-Aligned-Grid功能,将它们组合在一起



然后,我们创建一个SceneTexture节点,并将Sobel-Edge和World-Aligned-Grid的结果添加到该节点。

然后,使用在第一部分中创建的环形蒙版的结果,在正常场景和添加的场景之间进行插值



瞧,我们做到了。 最终结果将如下所示。 当然,您可以调整参数并尝试更改其值以获得更多有趣的选项。



我希望您能找到所有有用的信息:)

可以在github上找到带有此着色器的示例项目。

Source: https://habr.com/ru/post/zh-CN435240/


All Articles