在虚幻引擎中使用渲染目标进行绘图


渲染目标本质上是可以在运行时写入的纹理。 从引擎的角度来看,它们存储诸如基础色,法线和环境光遮挡的信息。

从用户的角度来看,渲染目标主要用作一种附加相机。 您可以在某个点设置场景捕获并将图像保存在渲染目标中。 然后,您可以在网格上显示渲染目标,例如,模拟监视摄像机。

在4.13引擎版本发布之后,Epic添加了使用钝器将材料直接绘制到渲染目标的功能。 此功能使您可以创建复杂的效果,例如流体模拟和雪变形。 听起来很棒吧? 但是在进行此类复杂的效果之前,最好先熟悉一些简单的东西。 有什么比在渲染目标上绘制更简单的呢?

在本教程中,您将学到以下内容:

  • 用钝器动态创建渲染目标
  • 在网格上显示渲染目标
  • 在渲染目标上绘制纹理
  • 在游戏过程中更改笔刷大小和纹理

注意:本教程假定您已经熟悉使用虚幻引擎的基础知识。 如果您不熟悉虚幻引擎,请查看我们的面向初学者虚幻引擎教程系列,共十部分。

开始工作


让我们从下载本教程的资料开始(您可以在此处获得)。 解压缩它们,转到CanvasPainterStarter并打开CanvasPainter.uproject 。 如果点击播放 ,将会看到以下内容:


中间的方块(画布)是我们要绘制的。 左侧的UI元素将是我们要绘制的纹理及其大小。

首先,让我们看一下绘制方法。

画图方法


我们需要的第一件事是一个渲染目标,用作画布。 为了确定在渲染目标上绘制的位置,我们将跟踪从摄像机出来的直线。 如果线条与画布相交,则可以得到UV空间中的相交。

例如,如果画布具有完美的UV坐标绑定,则中心的相交处将返回值(0.5,0.5) 。 如果线条穿过右下角的画布,则将获得值(1,1) 。 然后,您可以使用简单的计算来计算图形的位置。


但是为什么要在UV空间中获得坐标? 为什么不使用世界真实空间的坐标呢? 在使用世界空间时,我们首先必须计算相对于平面的交点。 您还必须考虑平面的旋转和比例。

使用UV空间时,不需要所有这些计算。 在具有UV坐标完美绑定的平面上,与平面的交点始终返回(0.5,0.5) ,而与平面的位置和旋转无关。

注意:本教程中考虑方法通常仅适用于平面或类似于平面的曲面。 其他类型的几何需要更复杂的方法,我将在另一篇教程中介绍。

首先,我们将创建将渲染渲染目标的材质。

创建画布材质


转到“ 材料”文件夹并打开M_Canvas

在本教程中,我们将使用钝器动态创建渲染目标。 这意味着我们必须将纹理设置为参数,以便可以将其传递给渲染目标。 为此,创建一个TextureSampleParameter2D并将其命名为RenderTarget 。 然后将其连接到BaseColor


现在,不必担心选择纹理-我们稍后会在蓝图中进行处理。 单击“ 应用” ,然后关闭M_Canvas

下一步是创建渲染目标,然后将其用作画布材料。

创建渲染目标


有两种创建渲染目标的方法。 首先:通过单击添加新\材质和纹理\渲染目标在编辑器中创建。 此方法使您可以方便地将同一渲染目标引用到多个角色。 但是,如果我们需要多个画布,则必须为每个画布手动创建一个渲染目标。

因此,最好使用钝器创建渲染目标。 这种方法的优势在于,我们仅在必要时创建渲染目标,并且它们不会增加项目文件的大小。

首先,我们需要创建一个渲染目标并将其保存为变量以备将来使用。 转到Blueprints文件夹并打开BP_Canvas 。 找到事件BeginPlay并添加选定的节点。


将“ 宽度”和“ 高度”设置为1024 。 因此,我们将渲染目标的分辨率更改为1024×1024 。 值越高,图像质量越高,但是视频存储器的成本也越高。


接下来是“ 清除渲染目标2D”节点。 我们可以使用此节点设置渲染目标的颜色。 将清除颜色设置为(0.07,0.13,0.06) 。 在这种情况下,整个渲染目标将用绿色填充。


现在,我们需要在画布网格上显示渲染目标。

渲染目标显示


此时,画布网格使用默认材质。 要显示渲染目标,您需要创建M_Canvas的动态实例并将渲染目标传递给它。 然后,您需要将材质的动态实例应用于画布网格。 为此,我们将添加选定的节点:


首先,让我们进入“ 创建动态材料实例”节点,并将“ 父级”值设置为M_Canvas 。 因此,我们将创建一个M_Canvas的动态实例。


接下来,转到“ 设置纹理参数值”节点,并将“ 参数名称”设置为RenderTarget 。 因此,我们会将渲染目标传递给之前创建的texture参数。


现在,渲染目标将显示在画布网格上。 单击编译,然后返回主编辑器。 单击播放以查看画布如何改变颜色。


现在我们有了画布,我们需要创建可用作画笔的材料。

创建画笔材质


转到“ 材料”文件夹。 创建材质M_Brush并打开它。 首先将混合模式设置为半透明 。 这将使我们能够使用具有透明度的纹理。


与画布材料一样,我们将画笔的纹理设置为钝器。 创建一个TextureSampleParameter2D并将其命名为BrushTexture 。 如下连接:


单击“ 应用” ,然后关闭M_Brush

接下来要做的是创建笔刷材质的动态实例,以便您可以更改笔刷的纹理。 打开BP_Canvas并添加选定的节点。


接下来,转到“ 创建动态材料实例”节点并将“ 级”设置为M_Canvas


我们创建了笔刷材质,现在我们需要一个函数用笔刷在渲染目标上进行绘制。

在渲染目标上进行画笔绘画


创建一个新函数并将其命名为DrawBrush 。 首先,我们需要以下参数:使用的纹理,画笔大小和绘制位置。 创建以下输入:

  • BrushTexture:选择类型“ Texture 2D”
  • BrushSize:选择浮动类型
  • DrawLocation:选择类型为Vector 2D


在绘制画笔之前,我们需要设置其纹理。 为此,创建如下所示的电路。 确保选择BrushTexture作为“ 参数名称”


现在我们需要在渲染目标中进行渲染。 为此,创建选定的节点:


“开始画布绘制到渲染目标”将使引擎知道我们要开始渲染到特定的渲染目标。 绘制材料允许您以选定的大小和旋转度在指定位置绘制材料。

计算渲染位置是一个两步过程。 首先,我们需要缩放DrawLocation以适合渲染目标分辨率。 为此,将DrawLocation乘以Size


默认情况下,引擎将以左上角为起点渲染材质。 因此,笔刷纹理将不会以我们要渲染的位置为中心。 要解决此问题,我们需要将BrushSize除以2 ,然后从上一步中减去结果。


然后,我们按以下方式连接所有内容:


最后,我们需要告诉引擎我们要停止在渲染目标中渲染。 将“ 最终绘图画布”添加到“渲染目标”节点,并按如下所示进行连接:


现在,每次执行DrawBrush时,它将首先将传输的纹理设置为BrushMaterial的纹理。 然后,她将使用传递的位置和大小在RenderTarget中渲染BrushMaterial

至此,渲染功能已准备就绪。 单击编译,然后关闭BP_Canvas 。 下一步是从摄像机追踪线,并在发生相交的画布位置绘制。

相机直接跟踪


在画布上绘制之前,我们需要指定画笔的纹理和大小。 转到Blueprints文件夹并打开BP_Player 。 然后将BrushTexture变量设置为T_Brush_01 ,并将BrushSize变量设置为500 。 因此,我们为猴子分配了500×500像素大小的画笔图像。


接下来,您需要跟踪该行。 找到InputAxis Paint并创建以下图:


因此,当玩家按住分配给Paint的键(在我们的情况下,这是鼠标左键 )时,我们将跟踪从相机直接指向的直线。

现在我们需要检查笔直的画布是否交叉。 添加选定的节点:


现在,当线条和画布相交时 ,将使用传递给它的画笔变量和UV坐标执行DrawBrush函数。

为了使“ 查找碰撞” UV节点起作用,我们需要更改两个参数。 首先,转到LineTraceByChannel节点并启用 Trace Complex


其次,转到“ 编辑\项目设置” ,然后转到“ 引擎\物理” 。 启用“ 从命中结果获得支持UV”并重新启动项目。


重新启动后,要在画布上绘制,请单击“ 播放”然后单击鼠标左键


您甚至可以创建多个画布,并分别在每个画布上进行绘制。 这是可能的,因为每个画布都会动态创建自己的渲染目标。


在下一节中,我们将实现更改玩家画笔大小的功能。

调整笔刷


打开BP_Player并找到InputAxis ChangeBrushSize节点。 将此轴绑定配置为使用鼠标滚轮 。 要更改笔刷大小,我们足以根据Axis Value更改BrushSize值。 为此,请创建以下方案:


当播放器使用鼠标滚轮时,它将从BrushSize执行加法或减法。 第一次乘法确定加法或减法的速率。 夹钳(浮动)已添加为安全措施。 这样可以确保画笔大小不会小于0或大于1000

单击编译,然后返回主编辑器。 旋转鼠标滚轮以在绘制时调整画笔的大小。


在最后一部分中,我们将创建一个功能,允许播放器更改笔刷的纹理。

更改笔刷纹理


首先,我们需要一个数组来存储播放器可以使用的纹理。 打开BP_Player并创建一个数组变量。 选择它的Texture 2D类型并将其命名为Textures


然后在Textures中创建三个元素。 为他们分配以下值:

  • T_Brush_01
  • T_Brush_02
  • T_Brush_03


这些将是玩家可以绘制的纹理。 要添加新纹理,只需将它们添加到此数组中。

接下来,我们需要一个变量来存储数组的当前索引。 创建一个整数变量,并将其命名为CurrentTextureIndex


接下来,我们需要一种循环遍历所有纹理的方法。 在本教程中,我设置了一个名为NextTexture的动作映射,并将其绑定到鼠标右键 。 当玩家按下此键时,应执行到下一个纹理的过渡。 为此,请找到InputAction NextTexture节点并创建以下图:


每次单击鼠标右键,此方案都会增加CurrentTextureIndex 。 如果索引到达数组的末尾,则它将再次重置为0 。 最后, BrushTexture设置适当的纹理。

单击编译,然后关闭BP_Player 。 单击播放然后单击鼠标右键以在纹理之间切换。


接下来要去哪里?


可以从此处下载完成的项目。

渲染目标是一个非常强大的工具,在本教程中,我们仅介绍了基础知识。 如果您想知道哪些渲染目标能够使用,请在UE4中签出Content-Driven Multipass Rendering 。 该视频包含绘图流程图,体积绘图,流体模拟等示例。

另外,请观看我们的“ 绘制图纸以渲染目标”教程视频,以了解如何使用渲染目标创建高度图。

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


All Articles