UE4网格动态绘图
网格绘画是玩家在游戏中的物体上绘画的能力。网格绘画的例子有Super Mario Sunshine中的 goop、 Portal 2中的凝胶和Splatoon中的墨水。它可以用作游戏元素,也可以纯粹用于视觉效果。无论哪种方式,网格绘画都为游戏设计师和艺术家开辟了许多可能性。
尽管前面的示例都是几乎相同的效果,但你也可以使用网格绘画来制作许多其他效果。例如,可以使用它来喷涂物体、渲染角色的伤口,甚至让玩家绘制自己角色的脸!
在本教程中,我们将学习如何在骨架网格物体上绘画,主要步骤包括:
- 将网格展开为其 UV 形式
- 使用线跟踪中的命中位置对网格进行球面遮罩
- 使用场景捕获将展开的网格和球体蒙版渲染到渲染目标
- 使用蒙版在角色材质中的纹理之间进行混合
请注意,这不是关于顶点绘制的教程。顶点绘制取决于网格分辨率,不能在游戏运行时更改。另一方面,本教程中的方法独立于网格分辨率工作,也可以在游戏运行时工作。
1、准备
首先下载本教程的材料(可以在教程底部找到链接)。解压缩并导航到MeshPainterStarter并打开MeshPainter.uproject。如果按Play按钮,将看到要在其上绘画的角色。
就像雪地和草地痕迹教程一样,我们实现网格绘画也需要场景捕捉。为了节省时间,我已经创建了场景捕捉蓝图。如果想了解更多关于捕捉设置的信息,请查看创建雪痕的教程。
首先,让我们看看如何在网格上绘画。
2、网格绘画
在大多数情况下,我们使用的网格都是已经 UV 映射的。因此,显而易见的事情是使用渲染目标(Render Target)创建一个遮罩,然后将其应用于网格。但是,直接在渲染目标上生成遮罩(使用 Draw Material to Render Target)通常会导致 UV 壳之间的不连续性。
这是一个立方体的 UV 贴图和球体蒙版纹理的示例:
这是应用于立方体的蒙版:
如上图所见,2D 球体蒙版不会环绕角落,因为它没有考虑几何形状。要生成正确的遮罩,球体遮罩需要对网格的世界位置进行采样。但是在使用 Draw Material to Render Target 节点时如何访问世界位置呢?
如果你在研究网格绘画的方法,可能已经看过 Ryan Bruck 的关于使用渲染目标实现角色毁损的视频(本教程基于其方法)。在视频中,他成功生成了 3D 球体蒙版,并将其累积到渲染目标中。Ryan之所以能够做到这一点,是因为他创建了一个渲染目标来存储网格的世界位置,然后他可以使用球体蒙版对其进行采样。让我们仔细看看。
3、Ryan的世界位置采样方法
Ryan的方法有四个步骤。第一步是“展开”有问题的网格。这只是简单地移动所有顶点,以便获得 UV 形式的网格。例如,这里是角色的 UV:
这是在虚幻中展开后的角色:
可以通过应用一些简单的世界位置偏移数学来展开网格(稍后将看到)。
展开后,第二步是将网格的世界位置编码为渲染目标。为此,可以将展开材质的颜色设置为绝对世界位置,然后使用场景捕捉来捕捉展开。这是渲染目标的样子:
注意:渲染目标会改变颜色,因为角色是运动的。这导致世界位置不断变化。
第三步是创建球体蒙版。现在可以访问网格的世界位置,因此可以在球体蒙版中对其进行采样。然后,可以将球体蒙版直接绘制到第二个渲染目标。
最后一步是使用角色材质中的蒙版在颜色、纹理或材质之间进行混合。以下是可视化的步骤三和四:
现在,让我们看看建议的方法。
4、我们建议的方法
虽然 Ryan 的方法有效,但它需要:
- 需要两个渲染目标进行绘制。首先是捕获展开的网格,然后是汇总球体蒙版。
- 一个渲染目标用于存储世界位置
- 另一个渲染目标用于累积球体蒙版,我们需要为每个要在其上绘制的actor 设置一个单独的渲染目标。
本教程中的方法避免了第二次绘制及世界位置渲染目标。方法通过将展开和球形遮罩组合成一种材料(展开材料)来实现此目的。然后,使用加法合成模式捕获展开以累积球体蒙版。
需要注意的一点是,当网格没有重叠 UV 时,这两种方法都最有效。重叠的 UV 将导致共享相同 UV 空间的像素也共享相同的蒙版信息。例如,将双手 UV 映射到同一空间。如果一只手进行了蒙版处理,另一只手也一样。
现在让我们从创建展开材料开始。
5、创建展开材质
导航到Materials文件夹并创建一个新材质。将其命名为M_Unwrap,然后打开它。
接下来,更改以下设置:
- 着色模型:Unlit。这是为了确保场景捕获不会捕获任何照明信息。
- 双面:启用。有时,根据网格的 UV 映射方式,展开的面可能会面向另一个方向。双面将确保我们可以看到任何翻转的面。
- 与骨架网格体一起使用:启用。这将编译材质在骨架网格物体上工作所需的着色器。
接下来是展开网格。为此,请创建以下设置。请注意,我已经在MPC_Global资产中创建了CaptureSize和UnwrapLocation参数。
这会将网格 UV 展开到指定大小的指定位置。请注意,如果网格的唯一 UV 贴图位于单独的通道上,则需要更改TextureCoordinate节点的坐标索引。例如,如果唯一的 UV 在通道 1 上,可以将Coordinate Index设置为1。
下一步是创建球体蒙版。为此,我们将需要两个参数:命中位置和球体半径。创建突出显示的节点:
这将为球体蒙版内的像素返回白色,为外部的像素返回黑色。不必担心为参数设置值,因为稍后我们将在蓝图中这样做。
将Absolute World Position节点设置为Absolute World Position (Excluding Material Shader Offsets)很重要。这是因为像素的世界位置会因为展开而改变。排除材质着色器偏移将为我们提供展开前的原始世界位置。
这就是展开材质所需的全部内容。单击应用,然后关闭材质编辑器。接下来是将材质应用到角色以展开它。
6、展开角色
对于本教程,捕获蓝图将处理展开和捕获。首先,我们需要展开材质的动态实例。导航到Blueprints文件夹并打开BP_Capture。然后,将突出显示的节点添加到Event BeginPlay。确保将Parent设置为M_Unwrap。
接下来,我们需要一个函数来执行展开和捕获。创建一个名为PaintActor的新函数。之后,创建以下输入:
- ActorToPaint:类型是Actor。Actor展开和捕捉。
- HitLocation:类型为Vector。这将是球体蒙版的中心点。
- BrushRadius:类型为Float。以世界单位表示的球体蒙版的半径。
虽然这种绘画方法可以与任何Actor一起工作,但我们只会检查传入的Actor是否继承自Character类。为了简化代码,我们将角色的骨架网格组件存储到一个变量中,因为我们将多次引用它。为此,请添加突出显示的节点:
现在是时候进行展开和球体蒙版了。为此,请将突出显示的节点添加到节点链的末尾:
以下是每行的作用:
- 首先,这将保存网格的原始材质,以便我们以后可以重新应用它。之后,它将应用展开材料。
- 这条线将在命中位置和笔刷半径中传递到展开材质以进行球体遮罩
在测试展开之前,我们需要从玩家处进行线跟踪以获得命中位置。
7、获取命中位置
单击编译,然后返回主编辑器。之后,打开BP_Player。打开Shoot功能并添加突出显示的节点。对于本教程,将笔刷半径设置为10。
单击编译,然后关闭BP_Player。按播放,然后左键单击角色以进行展开和球体蒙版。
你可以想知道为什么遮罩一直在移动,那是因为部件正在进出球面遮罩。但这不是问题,因为我们只会在命中时捕获展开。
现在已经展开了网格,让我们捕获它。
8、捕获展开
首先,最好在展开的网格后面添加一个不亮的黑色平面。这将有助于防止 UV 壳边缘出现接缝。打开BP_Capture,然后添加一个名为BackgroundPlane的平面组件。为了节省时间,我已经为你创建了黑色材料。将材质设置为M_Background。
对于本教程,展开和捕获大小为500×500单位,因此背景平面至少需要那么大。将比例设置为(5.0, 5.0, 1.0)。
由于平面的位置和展开位置相同,因此最好将平面向下偏移以防止任何 z 轴冲突。为此,请将Location设置为(0.0, 0.0, -1.0)。
接下来,我们需要执行捕获。返回到PaintActor函数并添加突出显示的节点:
这将捕获展开的网格。之后,它将重新应用网格的原始材质。
目前,场景捕获将覆盖渲染目标的先前内容。为确保球体蒙版累积,我们需要确保场景捕获添加到先前的内容中。为此,请选择SceneCapture组件并将Scene Capture\Composite Mode设置为Additive。
单击编译,然后关闭蓝图。接下来,我们需要在角色的材质中使用渲染目标。
9、使用蒙版
导航到Characters\Mannequin\Materials并打开M_Mannequin。然后,添加突出显示的节点。确保将Texture Sample设置为RT_Capture。
这将在蒙版为白色的地方显示红色,在蒙版为黑色的地方显示橙色。但是,如果愿意,我们可以在纹理或材质层之间进行混合。
单击应用,然后关闭材料。按播放并左键单击角色开始绘画。
原文链接:UE4动态网格绘画 — BimAnt