[size=1.0625]直到最近,游戏中的草通常由地面上的纹理表示,而不是渲染单个草叶。但是随着硬件功能的增强,我们渲染草的能力也随之增强。您可以在《地平线零黎明》和《塞尔达传说:旷野之息》等标题中看到此类示例。在这些称号中,玩家可以穿过草地,但更重要的是,草对玩家有反应。
[size=1.0625]幸运的是,创建一个可以做到这一点的系统并不是很困难。实际上,您今天将要学习如何做!在本教程中,您将学习如何:
- 使用场景捕捉和粒子系统创建矢量场
- 通过使用矢量场将草弯曲远离玩家
注意:本教程假定您已经了解使用虚幻引擎的基础知识。如果您不熟悉虚幻引擎,请查看我们的10部分虚幻引擎初学者教程系列。特别是,请查看“粒子系统”教程,因为您将需要知道如何在本教程中使用Cascade。
注意:本教程是关于在虚幻引擎中使用渲染目标的3部分教程系列的一部分:
入门[size=1.0625]首先下载本教程的资料(您可以在本教程的顶部或底部找到一个链接)。解压缩并导航到InteractiveGrassStarter并打开InteractiveGrass.uproject。您将看到一小片草地,将作为本教程的主题。我还创建了一个小部件来显示场景捕获的渲染目标。
[size=1.0625] [size=1.0625]在开始之前,请确保您已经阅读了有关创建雪道的教程,因为我将跳过该教程中的一些信息。请注意,本教程还将使用捕获和投影。为了节省时间,我还已经建立了一个捕获图,该图类似于积雪追踪教程中的图。 [size=1.0625]在深入研究之前,让我们看一下创建交互式草的另一种方法。最常见的方法是将玩家的位置发送到草地材料,然后使用球形蒙版在玩家的特定半径内弯曲草皮。
[size=1.0625]虽然这是一种不错的方法,但是如果您想添加更多影响草的演员,则无法很好地扩展。对于您添加的每个角色,您需要向材质添加另一个位置参数和球面罩。一种更好地缩放的方法是使用矢量场。
什么是向量场?[size=1.0625]向量场只是一个纹理,每个像素代表一个方向。如果您以前使用过流程图,它们是同一回事。但是,您将不使用移动UV,而是使用“世界位置偏移”销移动顶点。与球形蒙版方法不同,材料只需要对矢量场采样一次即可获得弯曲方向。 [size=1.0625]让我们看看如何将方向存储到纹理中。看一下这个网格:
[size=1.0625] [size=1.0625]假设红点是您要移动的对象。如果将其移动到右下角,则哪个矢量代表该移动?如果您回答(1,1),那么您是正确的!您可能知道,也可以将矢量表示为颜色,这就是将它们存储到纹理中的方式。让我们将此向量插入Unreal的颜色选择器中,看看它返回什么颜色。
[size=1.0625] [size=1.0625]如您所见,方向(1,1)返回黄色。这意味着,如果要向正XY轴弯曲草,只需要在纹理中使用此颜色即可。现在,让我们看一下所有矢量的颜色。
[size=1.0625] [size=1.0625]右下象限看起来很不错,因为它在两个轴上都有渐变。这意味着您可以将任何矢量存储在该象限中作为颜色,因为每个矢量都有唯一的颜色。
[size=1.0625]但是其他三个象限是有问题的。它们仅在一个轴上具有渐变,或者根本没有渐变。这意味着多个矢量将共享一种颜色。例如,将无法在向量(-1,1)和(0,1 )之间进行区分。
[size=1.0625]这三个象限的每个矢量没有唯一颜色的原因是,您只能使用0到1之间的值表示颜色。但是,三个象限使用的负值超出该范围。
[size=1.0625]解决方案是重新映射向量,使它们适合0到1范围内。您可以通过将向量乘以0.5,然后再加上0.5来实现。这是外观的可视化效果:
[size=1.0625] [size=1.0625]现在,每个向量都有独特的颜色。当需要将其用于计算时,只需要将其重新映射回-1到1范围。以下是一些颜色以及它们重新映射后所代表的方向:
- (0,0):负X和Y
- (0.5、0.5):无动作
- (0,1):负X和正Y
- (1,0):正X和负Y
[size=1.0625]接下来,让我们看看如何在虚幻引擎中创建向量字段。
创建矢量场[size=1.0625]与雪道不同,您不会捕获物体的形状。相反,您将使用“画笔”在渲染目标上进行绘制。这些将只是自定义矢量场的图像。我将这些称为方向刷。
[size=1.0625]除了使用Blueprints绘制到渲染目标外,还可以使用粒子。粒子将显示方向笔刷并从播放器发射。要创建矢量场,您只需使用场景捕获并仅捕获粒子。这种方法的优点是创建跟踪非常容易。它还使您可以轻松控制轨迹持续时间和大小等属性。由于粒子在离开并重新进入捕获区域后仍然存在,因此它们还会创建半持续的轨迹。
[size=1.0625]以下是一些可以使用的方向刷示例及其在草地上的效果。请注意,在下面的示例中粒子不可见。
[size=1.0625] [size=1.0625]首先,让我们创建显示方向笔刷的材质。
创建指导材料[size=1.0625]有两种创建方向笔刷的方法:
- 数学上:在此处定义材料内的方向和形状。这样做的好处是它不需要外部软件,并且易于制作简单的形状。
- 转换法线贴图:在这里可以创建所需方向和形状的法线贴图。要转换为可用的矢量场,只需删除蓝色通道。该方法的优点是您可以轻松创建复杂的形状。下面是一个很难在数学上进行复制的画笔示例。
[size=1.0625] [size=1.0625]对于本教程,您将在数学上创建一个。导航到“材质”文件夹,然后打开M_Direction。请注意,此材质的着色模型为Unlit。这很重要,因为这将允许场景捕获来捕获粒子,而不会影响光线。
[size=1.0625]为简单起见,您将创建一种材质,该材质将导致草从粒子中心移开。为此,请创建以下内容:
[size=1.0625] [size=1.0625]现在,您需要重新映射。为此,添加突出显示的节点并按如下所示连接所有内容:
[size=1.0625] [size=1.0625]接下来,让我们给它一个圆形。为此,添加突出显示的节点:
[size=1.0625] [size=1.0625]RadialGradientExponential是控制圆的大小和硬度的因素。将其与“粒子颜色”相乘将使您可以从粒子系统控制粒子的不透明度。我将在下一节中对此进行更详细的介绍。
[size=1.0625]这是刷子的样子:
[size=1.0625] [size=1.0625]单击“应用”,然后关闭材料。现在您已经创建了材质,是时候创建拖尾粒子系统了。
创建跟踪粒子系统[size=1.0625]导航到“ ParticleSystems”文件夹,然后打开PS_GrassTrail。为了节省时间,我已经创建了所有需要的模块。
[size=1.0625] [size=1.0625]以下是每个模块如何影响草丛的方式:
- 生成:生成速度会影响轨迹的平滑程度。如果您的步伐看起来“不稳定”,则应提高产卵率。对于本教程,我们将其保留为默认值20。
- 生命周期:草恢复到默认状态之前的路径持续时间
- 初始大小:步道大小
- 使用寿命内的颜色:由于在材质中使用了“粒子颜色”,因此可以在此处控制不透明度。您还可以调整Alpha曲线以控制轨迹的淡出方式。例如,您可以进行线性淡入,淡入和/或淡出。对于本教程,我们将其保留为默认值,即线性淡入淡出。
- 锁定轴:用于确保粒子面向场景捕获
- 初始旋转:用于确保粒子朝向正确的轴(稍后将详细介绍)
[size=1.0625]首先,您需要设置材料。选择Required模块,然后将Material设置为M_Direction。在这里时,还可以将“排序模式”设置为“ PSORTMODE年龄最短”。
[size=1.0625] [size=1.0625]此排序模式将确保较新的粒子将呈现在较旧的粒子之上。如果不这样做,则较旧的粒子可能会影响草,而不是较新的粒子。
[size=1.0625]接下来是路径的持续时间。选择Lifetime模块,并将Constant设置为5。这将导致足迹在五秒钟内消失。
[size=1.0625] [size=1.0625]接下来是路径的大小。选择“初始大小”模块,然后将“常量”设置为(150,150,0)。这将使每个粒子覆盖150×150的区域。
[size=1.0625] [size=1.0625]现在,您需要确保粒子面向场景捕获。由于在本教程中场景捕获是从上方捕获的,因此粒子将需要面向Z轴正方向。要做到这一点,选择锁定轴模块,并设置锁定轴标记到ž。
[size=1.0625] [size=1.0625]最后,您需要设置粒子的旋转。当前,画笔中的颜色与它们表示的方向不一致。这是因为默认情况下,粒子系统将应用90度旋转。要解决此问题,请选择“初始旋转”模块,并将“常量”设置为-0.25。这会将粒子逆时针旋转90度。
[size=1.0625] [size=1.0625]这就是粒子系统所需的全部内容,因此继续进行操作并关闭它。
[size=1.0625]接下来,您需要将粒子系统附加到要创建轨迹的任何对象上。在这种情况下,您会将其附加到玩家角色。
附着粒子系统[size=1.0625]导航到Characters \ Mannequin并打开BP_Mannequin。然后,创建一个Partice System组件并将其命名为GrassParticles。
[size=1.0625] [size=1.0625]接下来,您需要设置粒子系统。转到“详细信息”面板,并将“粒子\模板”设置为PS_GrassTrail。
[size=1.0625] [size=1.0625]如果玩家可以在游戏中看到步道,那将很奇怪,因此最好将其隐藏在玩家面前。为此,启用Rendering \ Owner No See。
[size=1.0625] [size=1.0625]由于粒子系统已附加到播放器(所有者)上,因此播放器将看不到它,但其他所有东西仍然可见。
[size=1.0625]单击编译,然后按播放。请注意,粒子不会出现在播放器相机中,而是仍然显示在渲染目标中。
[size=1.0625] [size=1.0625]现在,场景捕获已设置为捕获所有内容。显然这是不好的,因为颗粒是唯一会影响草的东西。在下一节中,您将学习如何仅捕获粒子。
捕获粒子[size=1.0625]如果立即捕获粒子,则在没有粒子的区域中会发生不希望的弯曲。这是因为渲染目标的背景色为黑色。发生弯曲是因为黑色代表向负XY轴移动(重新映射后)。为了确保空白区域没有移动,您需要确保渲染目标的背景色为(0.5,0.5,0)。一种简单的方法是创建一架巨型飞机,并将其固定在玩家身上。
[size=1.0625]首先,让我们为背景创建材料。返回到内容浏览器并打开Materials \ M_Background。然后,将(0.5,0.5,0 )的常量连接到Emissive Color。
[size=1.0625] 注意:就像粒子材质一样,您计划捕获的任何材质都需要关闭。
[size=1.0625]单击“应用”,然后关闭材料。返回BP_Mannequin,然后创建一个新的Plane组件。将其命名为Background。
[size=1.0625] [size=1.0625]接下来,设置以下属性:
- 位置:(0,0,-5000)。这会将其放置得足够低,以使其不会阻塞任何颗粒。
- 比例尺:(100,100,1)。这样可以将其缩放到足够大的程度,以使其覆盖捕获区域。
- 材质: M_背景
[size=1.0625] [size=1.0625]就像粒子一样,如果玩家看到它们下方的黄色巨型飞机,那将很奇怪。要隐藏它,请启用Rendering \ Owner No See。
[size=1.0625] [size=1.0625]现在已经设置了背景,是时候捕获粒子了。您可以通过将粒子系统添加到场景捕获的仅显示列表中来实现。这是场景捕获将专门捕获的组件列表。
使用仅显示列表[size=1.0625]在可以将其添加到仅显示列表之前,需要一种方法来获取所有影响草的演员。一种方法是使用标签。标签只是可以分配给角色和组件的字符串。然后,您可以使用“使用标签获取所有演员”节点来获取具有特定标签的所有演员。
[size=1.0625]由于玩家演员应该影响草地,因此将需要标签。要添加标签,请首先单击“ Class Defaults”按钮。然后,在Actor \ Tags下创建一个新标签,并将其命名为GrassAffector。
[size=1.0625] [size=1.0625]由于仅显示列表仅接受组件,因此您还需要将标签添加到影响草的组件。选择GrassParticles组件,然后在“标签”部分下添加一个新标签。将它命名为GrassAffector以及(你不具备使用该标签)。对“背景”组件执行相同的操作。
[size=1.0625] [size=1.0625]现在,您需要将所有影响草的组件添加到捕获的仅显示列表中。单击编译,然后关闭BP_Mannequin。然后,打开Blueprints \ BP_Capture。转到事件BeginPlay并添加突出显示的节点。确保也设置了指示的引脚。
[size=1.0625] [size=1.0625]这将循环所有具有GrassAffector标签的演员。然后它将检查actor是否具有带有相同标签的任何组件,并将它们添加到仅显示列表中。
[size=1.0625]接下来,您需要告诉场景捕获使用仅显示列表。选择SceneCapture组件,然后转到“场景捕获”部分。将基本渲染模式设置为使用ShowOnly列表。
[size=1.0625] [size=1.0625]单击编译,然后关闭蓝图。如果按Play,您将看到渲染目标现在仅捕获粒子和背景平面。
[size=1.0625] [size=1.0625]接下来是您一直在等待的部分。是时候让草弯曲了!
弯曲草[size=1.0625]首先,您需要将渲染目标投影到草地上。转到“材料”文件夹并打开M_Grass。然后,创建下面的节点。确保将纹理设置为RT_Capture。
[size=1.0625] [size=1.0625]由于您已将颜色重新映射到0到1的范围,因此在使用之前需要将其重新映射回-1到1。为此,添加突出显示的节点:
[size=1.0625] [size=1.0625]现在您有了弯曲的方向,您需要一些方法将草向该方向旋转。幸运的是,已经有一个名为RotateAboutAxis的节点。继续创建一个。
[size=1.0625] [size=1.0625]让我们从NormalizedRotationAxis引脚开始。顾名思义,这是顶点将绕其旋转的轴。为了计算这个,你只需要跨产品与弯曲方向(0,0,-1) 。为此,添加突出显示的节点: [size=1.0625] [size=1.0625]接下来是RotationAngle,它是顶点应围绕枢轴旋转的角度。默认情况下,期望值介于0和1之间,其中0是0度,而1是360度。要获得旋转角度,可以使用弯曲方向的长度乘以最大旋转。
[size=1.0625] [size=1.0625]乘以最大旋转数0.2表示最大旋转角度为72度。
[size=1.0625]计算PivotPoint有点棘手,因为一个草网格包含多个草叶片。这意味着您不能使用“对象位置”节点之类的东西,因为那样会为所有草刀片返回相同的点。
[size=1.0625]理想情况下,您将使用3D包将枢轴点存储在UV通道内。但是对于本教程,我们将仅估算一个枢轴点。这样做的方法是简单地从顶部向下移动一定的偏移量。
[size=1.0625] [size=1.0625]为此,添加突出显示的节点:
[size=1.0625] [size=1.0625]在本教程中,草高约80个单位,这就是为什么我将PivotOffset设置为该值的原因。
[size=1.0625]接下来,您将需要执行两个遮罩。第一个遮罩将确保草叶的根部不动。第二个遮罩将确保捕获区域之外的草不受矢量场的影响。
掩蔽[size=1.0625]在本教程中,我设置了草草的顶点颜色,以使底部顶点为黑色,顶部顶点为白色。
[size=1.0625] [size=1.0625]要掩盖根,只需将RotateAboutAxis的结果与“顶点颜色”节点相乘即可。
[size=1.0625] [size=1.0625]要遮盖捕获区域之外的草,请将先前的结果与突出显示的节点相乘:
[size=1.0625] [size=1.0625]单击“应用”,然后关闭材料。按下Play键,然后开始四处奔跑,在草地上步履蹒跚!
[size=1.0625] 然后去哪儿?[size=1.0625]您可以使用本教程顶部或底部的链接下载完成的项目。
[size=1.0625]尽管本教程中的方法适用于诸如草之类的简单事物,但在需要更多动态性的对象上使用该方法时可能会不足。减轻这种情况的一种方法是使用树叶的物理版本。请查看有关交互式叶子的这篇文章,以获取更多信息。