NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - AI模型在线查看 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 - 3D道路快速建模
本文将介绍使用蓝图和后期处理效果创建玩家视野可视化效果所需的所有步骤。
主要内容包括
- 在玩家/对象周围进行径向追踪以寻找障碍物
- 使用实例化静态网格 (ISM) 组件中的三角形“切片”网格绘制通畅区域直到跟踪命中或跟踪结束
- 将 ISM 径向切片捕获到渲染目标(Render Target)
- 沿世界空间坐标对渲染目标进行采样以用作后期处理蒙版
- 为后期处理蒙版添加屏幕空间烟雾效果
本文假设读者对虚幻引擎的蓝图脚本系统和材质系统有中等程度的熟悉。我们将从 Top-Down 项目模板开始,在 UE4 4.20.3 中工作,不过此处探讨的概念应该可以一直到最新版本的虚幻引擎。
1、检测周围障碍物
让我们从障碍物检测开始。出于本文的目的,我会将相关内容存储在名为 SightLine 的文件夹中,不过你可以随意组织文件。在你选择的文件夹中,创建一个新的蓝图类,使用 Actor 作为父类,将其命名为 BP_SightLine 或类似名称,然后在 Event Graph中打开。
参考下图创建必要的变量:
视野可视化系统的核心部分是绕Z轴 360° 旋转线迹,用于查找可见区域中心点与周围障碍物之间的距离。为此,我们将使用 For 循环,将 Trace Count 或 360° 旋转中的总跟踪线数除以 360,然后将结果乘以 CurrentTraceStep,即循环的当前索引。你可以通过更改跟踪计数来控制这些跟踪对性能的影响,但这会直接影响准确性,尤其是当在远离中心点的障碍物上受到撞击时。在我的测试中,我发现 1:1 的轨迹与旋转度数的比率可提供可接受的精度,而不会影响性能,因此这将是我们的轨迹计数默认值。
创建一个自定义事件,将其命名为 SightTrace,并设置以下逻辑:
在这里,你可以在 ForLoop 的每一步中看到,根据轨迹数与其与完整 360 度旋转的关系计算旋转度数。这被输入到Actor前向向量的旋转中,因此在循环的每一步中,轨迹都在旋转,直到每个方向上的轨迹均匀分布并被考虑在内。为了可视化这一点,在 LineTraceByChannel 节点中将 Draw Debug Type 设置为 For Duration 并将 Draw Time 设置为 0.1,然后在构造脚本中调用 SightTrace 事件,如下所示:
然后将 BP_SightLine actor 放在关卡中并拖动它,应该会看到跟踪行为突出显示从 actor 位置检测到的障碍物:
特别好!现在我们已经设置并参数化了跟踪行为,可以应用从跟踪中获得的数据来扩展 Instanced Static Mesh 组件中的实例。但首先,我们需要一个三角形“切片”网格,它在视觉上表示中心点和两个周围点旋转 1 度的变化。我本来打算介绍这个过程,但是由于 DAE 程序和在 Blender 中需要应用的缩放规则存在差异,这里仅提供一个下载链接。
将网格下载并导入项目后,可能会注意到它非常小。这是设计使然,因为它旨在按障碍物距离Actor位置的厘米数进行缩放,因此它被缩小到在其 X 轴上覆盖 1 厘米。
让我们继续使用实例化静态网格体组件绘制障碍物形状
2、可视化障碍物。
我们将最终将此实例化静态网格 (ISM) 绘制到渲染目标,因此我们需要将一个简单的材质应用于切片网格,以便可以轻松看到它。创建一个新材质并将其命名为“M_SightLineSlice”或类似名称。它应该如下图所示:
将 Two Sided 标志标记为 true 很重要,这样我们就可以轻松调试 ISM,并且我们将用于获取渲染目标蒙版的 Scene Capture 组件可以在设置 ISM 时看到它,这一点稍后会详细介绍。将对象设置为 Unlit 着色模型也很重要,这样它就不会收到任何阴影或来自某些其他渲染功能的影响。
打开 SM_SightLineVisSlice 网格资源,并将默认材质设置为我们的 M_SightLineTrace 材质,如下所示,然后可以保存并关闭 SM_SightLineVisSlice 和 M_SightLineSlice。
现在我们已经完成了网格准备,可以设置我们的 ISM 并应用一些逻辑来查看它的运行情况。
首先,在 BP_SightLine 中,单击 Add Component 并选择 Instanced Static Mesh。确保 Static Mesh 设置为 SM_SightLineVisSlice,Material 0 插槽中的 Material 设置为 M_SightLineSlice,并且 Collision Presets 字段设置为 NoCollision,如下所示:
接下来,创建一个自定义事件,并将其命名为“InitializeISM”或类似名称。将以下逻辑连接到它:
然后从LineTraceByChannel 节点,设置以下逻辑:
这将根据轨迹长度、向量和轨迹计数/度数比更新实例的比例和旋转。为了可视化这一点,在 LineTraceByChannel 节点上将 Draw Debug Type 设置为 None,并将构建脚本中的 SightTrace 节点替换为 InitializeISM 节点,如下所示:
在关卡中禁用 OffsetByHeight 并再次在关卡周围拖动Actor:
让 ISM 基于跟踪数据生成也非常有助于可视化 TraceCount 如何影响准确性,如下所示:
好的,现在我们让 ISM 生成交点的网格蒙版。我们可以通过让 actor 跟随 TopDownCharacter actor 并在运行时更新跟踪来了解它在运行时是如何工作的。
下面是实现逻辑:
首先,我们需要在 BeginPlay 事件中附加几个节点,以获取对我们希望 SightLine遵循的Actor类型的引用:
接下来,我们需要一些即时行为来将 SightLine 演员保持在我们的目标跟随Actor上。这里解释一下,你可以选择将 BP_SightLine 附加到你的玩家角色Actor。这只是一种更通用的方法,可以帮助你了解它的工作原理。
现在,当你使用 PlayInEditor 时,应该会看到 ISM 跟随玩家并根据周围的障碍物发生碰撞/重塑。具有讽刺意味的是,一旦我们设置了后期处理效果,遮挡地面视野的白色区域将作为可见区域,而障碍物后面的可见区域将被剔除。
现在我们从 ISM 和 Trace 信息中生成了一个白色遮罩,是时候通过重新启用 OffsetByHeight 来隐藏它了。这将使跟踪高度位置保持在 actor 位置,但将实例相对于 actor 向上移动(默认为 5000 个单位),以便它们位于自上而下的摄像机上方,因此不在视野范围内。为了应用此遮罩,我们需要使用正交场景捕获 2D 组件将其捕获到渲染目标,然后在后期处理材料中对该渲染目标进行采样。之后我们可以添加一些最终效果并完成!
3、捕获 ISM Visualizer 以渲染目标
返回 BP_SightLine 类,单击 Add Component 并选择 Scene Capture Component 2D,并将其 Projection Type 设置为 Orthographic。如果出于任何原因使用天空/大气Actor,请确保从“高级显示标志”部分禁用它。然后使用来自 Sight Trace 事件调用的以下逻辑附加 InitializeISM 事件,如下所示:
在内容浏览器中,创建一个渲染目标并将其命名为“RT_SightLineCapture”或类似名称。确保设置 Texture Render Target 2D 设置,如下图所示:
在 BP_SightLine 中,将 Scene Capture Component 2D Texture Target 值设置为 RT_SightLineCapture,并将 Capture Source 设置为 RGB 中的 Final Color (LDR)。
现在,当你打开 RT_SightLineCapture 资产并在编辑器中播放时,应该会看到 ISM 正交视图的更新,在播放屏幕上方看不见,但仍在捕获(倒置的图像)视线。
使用此图像,我们可以生成一个世界空间蒙版,以使用后期处理材质控制可见像素!
4、 ISM RT 后处理采样
我们将把它简化为一个材质函数,它只过滤 PostProcessInput0,这是 Post Process 材质中默认的最终渲染通道场景纹理,并剔除上面 RT 中红色区域未覆盖的像素。不过,要做到这一点,我们需要能够更新世界空间中的纹理大小,使其与我们的 CheckRange 匹配,并且我们还需要不断更新 actor 位置作为材质变量,这样我们就可以更改在世界空间中对纹理进行采样的位置。为此,我们需要创建一个材质参数集合,以便我们可以轻松访问蓝图和材质共享值。
在内容浏览器中,创建一个材质参数集合,并将其命名为“MPC_SightLine”或类似名称。打开它,创建一个标量参数,将其命名为 SightLineTexScale,并将默认值设置为 4000。然后创建第二个标量参数,将其命名为 SightLineMaskHeight,并将默认值设置为 4500。然后创建一个矢量参数,将其命名为 SightLineActorLocation ,但不要担心默认值,因为 BP_SightLine 会非常频繁地更改它。
说到这一点,回到 BP_SightLine 中,将 InitializeISM 字符串从我们之前离开的位置追加,以包含以下突出显示的代码:
然后使用以下突出显示的代码更新 Event Tick 字符串:
这样,BP_SightLine 对纹理采样/编码值所做的任何更改都会存储到材质可访问的位置。现在我们需要获取这些值和渲染目标,并使用材质函数将它们采样到后期处理材质中。因此,在内容浏览器中,创建一个材质函数,并将其命名为“MF_SightLineProjection”或类似名称,然后将其打开。
创建如下图所示的代码。
功能概览:
世界空间采样:
颜色混合:
样本覆盖防止:
确保像这样启用对库的公开:
现在我们准备使用此功能创建后期处理材料。创建一个新材质,并将其命名为“M_SightLineBlendable”或类似名称。然后右键单击该资产,并选择“创建材质实例”,并将新资产命名为“MI_SightLineBlendable”或类似名称。打开 M_SightLineBlendable,并创建以下代码:
确保将材质域设置为后期处理,并将可混合位置设置为半透明之前。保存此材质后,可以将其关闭,然后在关卡的后期处理体积 Rendering Features 类别中,将 MI_SightLineBlendable 资产应用到 Post Process Materials 数组,如下所示:
现在,当你在关卡中拖动 BP_SightLine actor 时,应该会看到后期处理效果掩盖了阻碍对象后面的像素!
但是,我们可以在这里看到一些伪影。纹理对齐对阻碍几何体的边缘过于尖锐,导致类似于 Z-fighting 的现象。幸运的是,我们已经在之前的代码构建中通过 Trace Hit Offset 变量采取了措施来阻止这种情况。这会沿着它们各自的跟踪向量缩放 ISM 切片,从而允许将未遮罩的区域从演员位置“推回”得更远,如下所示:
即便如此,蒙版(主观上)太锋利了。如果我们回到 MF_SightLineProjection 材质函数,我们可以添加一些逻辑来控制它的衰减。在“Samples RT in Worldspace,将其锐化以用作蒙版”注释部分中,将以下突出显示的代码添加到设置中,这将删除与其上方某些节点的连接:
值得注意的是,螺旋模糊功能确实有一些额外的渲染成本,所以在使用它时要小心。在这种情况下,它有助于软化边缘并使它们具有更多的衰减:
在本教程的这一点上,可以使用此设置在游戏中获得基本的视线效果。如果要更改颜色或在蒙版区域中添加纹理,可以更改此节点为希望包含的任何视觉效果,甚至将其更改为函数输入 (Vector3),如果想进一步参数化,则可以从后期处理材料中控制它的外观:
这篇文章的最后一步在技术上是可选的,但这将向你展示如何将烟熏效果应用于视线蒙版。
5、添加屏幕空间烟雾效果
如果想在本文的前两个 gif 中包含视觉效果,请继续下载此纹理作为我们的烟雾基础噪声,然后创建一个名为“MF_ScreenSpaceSmoke”或类似名称的新材质函数。
在 MF_ScreenSpaceSmoke 中,一定要勾选 Expose To Library,然后在下面的截图中创建代码。
将纹理与视口空间对齐:
噪声平移采样:
完成该功能的构建后,我们可以将其用作示例来更改视线遮罩的属性。在这种情况下,我们将使用它来:
- 扩大 UV 以使整个蒙版具有“波浪”效果,这反过来会略微扭曲边缘
- 从 SpiralBlur 通道调节边缘柔软度的强度和衰减
- 调制遮罩颜色以包括明暗区域,例如任意点亮的环境烟雾。
下面是将在 MF_SightLineProjection 中更新的代码图像:
移除旧的纹理采样通道:
调制遮罩颜色:
就是这样!
原文链接:TUTORIAL: Line of Sight Visualizer for Unreal Engine
BimAnt翻译整理,转载请标明出处