虚幻引擎 4 初学者教程——动态网格绘画

在此虚幻引擎 4 教程中,您将学习如何在任何类型的网格上绘制颜色。

网格绘画是玩家在游戏中的物体上绘画的能力。

网格绘画的例子有《超级马里奥阳光》中的粘液、《传送门 2》中的凝胶和《喷射战士》中的墨水。

它可以用作游戏元素,也可以纯粹用于视觉效果。

无论哪种方式,网格绘画为游戏设计师和艺术家开辟了很多可能性

虽然前面的示例几乎都是相同的效果,但您也可以使用网格绘制来实现许多其他效果。

例如,您可以用它来喷涂物体、渲染角色的伤口,甚至让玩家绘制自己角色的脸!


在本教程中,您将学习如何在骨架网格物体上绘画。

为此,您将:

  • 将网格展开为 UV 形式

  • 使用线迹中的命中位置来球体遮罩网格

  • 使用场景捕获将展开的网格和球体蒙版渲染到渲染目标

  • 使用蒙版在角色材质中的纹理之间进行混合

注意:这不是关于顶点绘制的教程。顶点绘制取决于网格分辨率,无法在游戏中更改。另一方面,本教程中的方法独立于网格分辨率,也适用于游戏。

*注意:本教程假定您已经了解使用虚幻引擎的基础知识。

如果您是虚幻引擎新手,请点击查看虚幻引擎初学者教程系列。*


本教程是关于在虚幻引擎中使用渲染目标的 4 部分教程系列的一部分:

第 1 部分:使用渲染目标绘画

第 2 部分:创建可交互雪地

第 3 部分:创建交互草地

第 4 部分:动态网格绘制

入门

点击下载本教程的资料链接

解压缩并导航到MeshPainterStarter并打开MeshPainter.uproject

如果你按Play,你会看到你要画的角色。

就像雪地和草地小径教程一样,这种方法也需要场景捕捉。

为了节省时间,我已经为您创建了一个场景捕捉蓝图。

如果您想了解有关捕捉设置的更多信息,请查看我们的可交互的雪地

首先,让我们看看如何在网格上绘画。

网格绘画

在大多数情况下,您正在使用的网格已经进行了 UV 映射。

所以显而易见的事情是使用渲染目标创建一个遮罩,然后将其应用于网格。

但是,直接在渲染目标上生成遮罩(使用 Draw Material to Render Target)通常会导致跨 UV 壳的不连续性。

这是立方体的 UV 贴图和球体遮罩纹理的示例:

这是应用于立方体的蒙版:

如您所见,2D 球体蒙版不会环绕角,因为它没有考虑几何形状。

要生成正确的蒙版,球体蒙版需要改为对网格的世界位置进行采样

但是在使用 Draw Material to Render Target 节点时如何访问世界位置呢?

创建展开材质

导航到Materials文件夹并创建一个新材料。将其命名为M_Unwrap然后打开它。

接下来,更改以下设置:

  • 着色模型:未点亮。这是为了确保场景捕获不会捕获任何照明信息。

  • 双面:启用。有时,根据网格的 UV 贴图方式,展开的面可以面向另一个方向。Two Sided 将确保您仍然可以看到任何翻转的面孔。

  • 用法\与骨架网格体一起使用:启用。这将编译材质在骨架网格物体上工作所需的着色器。

接下来是展开网格。

为此,请创建以下设置。

请注意,我已经在MPC_Global资产中创建了CaptureSize和UnwrapLocation参数。

这将 UV 展开网格到指定大小的指定位置。

请注意,如果您的网格的唯一 UV 贴图位于单独的通道上,您将需要更改TextureCoordinate节点的Coordinate Index

例如,如果唯一 UV 在通道 1 上,您可以将Coordinate Index设置为1。

下一步是创建球体蒙版。

为此,您需要两个参数:命中位置和球体半径。

创建突出显示的节点:

这将为球体遮罩内的像素返回白色,为外面的像素返回黑色。

不要担心为参数设置值,因为稍后您将在蓝图中进行设置。

Absolute World Position节点设置为Absolute World Position (Excluding Material Shader Offsets)很重要。

这是因为像素的世界位置会因展开而改变。

排除材质着色器偏移将为您提供展开前的原始世界位置。

这就是展开材料所需的全部内容。

单击“应用”,然后关闭材质。

接下来是将材质应用于角色以展开它。

展开角色

对于本教程,捕获蓝图将处理展开和捕获。

首先,您需要一个展开材质的动态实例。

导航到Blueprints文件夹并打开BP_Capture

然后,将突出显示的节点添加到Event BeginPlay

确保将Parent设置为M_Unwrap

接下来,您需要一个函数来执行解包和捕捉。创建一个名为PaintActor的新函数。

之后,创建以下输入:

  • ActorToPaint:类型是Actor。要解包和捕获的演员。-

  • HitLocation:类型是Vector。这将是球体遮罩的中心点。

  • BrushRadius:类型为Float。以世界单位表示的球体遮罩的半径。

虽然这种绘画方法可以适用于任何actor,但我们只会检查传入的演员是否继承自Character类。

为了简化代码,我们会将角色的骨架网格组件存储到一个变量中,因为您需要多次引用它。

为此,添加突出显示的节点:

现在是时候进行展开和球体遮罩了。

为此,将突出显示的节点添加到节点链的末尾:

这是每一行的作用:

  1. 首先,这将保存网格的原始材质,以便您稍后可以重新应用它。之后,它将应用展开材质。

  2. 这条线会将命中位置和笔刷半径传递给展开材质以进行球体遮罩

在您可以测试展开之前,您需要从播放器开始进行线跟踪以获得命中位置。

获取命中位置

单击编译,然后返回到主编辑器。

然后,打开BP_Player。打开拍摄功能并添加突出显示的节点。

对于本教程,将Brush Radius设置为10

单击Compile,然后关闭BP_Player

按播放键然后左键单击角色以执行展开和球形蒙版。

您想知道为什么蒙版一直在移动么,那是因为零件在球体蒙版中进进出出。

但这不是问题,因为您只会在命中时捕获解包。

现在您已经展开网格,您需要捕捉它。

捕捉展开

首先,在展开的网格后面添加一个未点亮的黑色平面是个好主意。这将有助于防止 UV 壳边缘出现接缝。

打开BP_Capture,然后添加一个名为BackgroundPlane的Plane组件。

为了节省时间,我已经为您制作了黑色材质。将材质设置为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

单击编译,然后关闭蓝图。接下来,您需要在角色材质中使用渲染目标。

使用遮罩

导航到Characters\Mannequin\Materials并打开M_Mannequin

然后,添加突出显示的节点。确保将Texture Sample设置为RT_Capture

这将在遮罩为白色的地方显示红色,在遮罩为黑色的地方显示橙色。

不过,如果您愿意,可以在纹理或材质层之间进行混合。

单击“应用”,然后关闭材质。按播放键左键单击角色开始绘画。

写在最后

虽然您在本教程中只使用了球体蒙版,但它们并不是您可以使用的唯一形状。

其他还有盒子、圆柱体、圆锥体等等!