Zack.Zhang Game Developer

虚幻4卡通渲染(Cel-Shading)教程(翻译)

2021-11-14
zack.zhang

原文:《Unreal Engine 4 Cel Shading Tutorial》

开发逼真的游戏对于虚幻4引擎来说很容易,因为引擎支持基于物理的渲染。这个模型模拟了光线如何与材料相互作用,从而产生了逼真的画面。然而,如果你想开发一款具有风格化外观的游戏,你就需要探索其他的技术。

实现风格化外观的一种方法是使用卡通渲染(Cel-Shading或者Toon-Shading)。这种技术模拟了一般用于卡通和动画中的着色。你可以在《Jet Set Radio》、《塞尔达传说:荒野之息》和《重力眩晕》(Gravity Rush)等游戏中看到这方面的例子。

在本教程中,你将学习如何:

  • 创建并使用后期处理材质(Post process material)

  • 创建一个卡通着色器(Cel Shader)

  • 将卡通着色器仅仅引用于场景中某些网格模型

  • 使用查找表(LUT)控制色带划分

注意:本教程假设你已经知道使用虚幻引擎的基础知识。如果你是虚幻引擎的新手,你应该首先回顾一下我们前面的10部分虚幻引擎初学者教程系列。

注意:本教程是虚幻引擎着色器教程系列的四个部分中的一部分:
第一部分:卡通渲染(Cel-Shading)(你在这儿)
第二部分:卡通描边(Toon Outlines)
第三部分:使用HLSL定制着色器
第四部分:油画滤镜

开始

下载初始工程并且解压缩。打开项目文件夹并打开CelShader.uproject。你会看到下面的场景:

unreal-engine-cel-shading-01

我们将对这个角色使用卡通着色。在开始之前,你要知道什么是卡通着色。

什么是卡通着色?

卡通着色是指使用多个色带来渲染某个物体,而不是用连续过渡的色彩来渲染。

unreal-engine-cel-shading-02

以下是《塞尔达传说:荒野之息》中的卡通渲染的例子。注意,只有角色使用了卡通着色而背景没有。

unreal-engine-cel-shading-03

在这个画面中,有三个色带。一个是阴影,一个是中间色调,一个是高光。

一个常见的误解是,如果某个物体有描边,它就是卡通渲染。《无主之地》就是一个例子。虽然这个游戏有一个风格化的画面,但它不是卡通渲染。可以看下面的图片。注意,角色并非使用色带来渲染。

unreal-engine-cel-shading-04

虽然描边并不是卡通渲染,但它们经常组合在一起使用。这有助于使图像看起来像是手绘的。你会在诸如《罪恶装备Xrd》(Guilty Gear Xrd)和《龙珠战士Z》(Dragon Ball FighterZ)等动画风格的游戏中看到很多这种情况。

unreal-engine-cel-shading-05

下一章,你将会学习到如何实现卡通渲染。

卡通渲染的方法

最常用的方法是比较表面方向(也就是法线方向)和光线方向。通过计算法线和光线方向之间的点积,你将得到一个介于-1和1之间的值。

值为-1意味着表面和光线朝向相反的方向。0表示它们互相垂直。1表示它们朝向同一个方向。

unreal-engine-cel-shading-06

通过对点积设置阈值,可以创建多个色带。例如,如果点积大于-0.8,你可以指定较深的颜色。如果点积小于-0.8,指定一个浅色。这将创建一个有着两个色带的卡通着色器。

unreal-engine-cel-shading-07

这种方法的限制是其他光线不能影响卡通着色的对象。同样,其他物体不能在卡通着色的物体上投影。

unreal-engine-cel-shading-01.gif

要解决这个问题,你需要使用不同的方法。不计算点积,而是计算表面的亮度。然后,你可以在阈值间使用这个值而不是点积。

unreal-engine-cel-shading-02.gif

现在,你知道什么是卡通着色器和它是如何工作的了,是时候创建一个了。

创建卡通着色器

本教程中的卡通着色是一种后期处理的效果。后期处理允许你在引擎完成渲染后更改图像。常用的后期处理有景深、运动模糊和Bloom等。

要创造你自己的后期效果,你需要使用后期处理材质(post process material)。打开工程中的Materials文件夹并创建一个新的材质。重命名为PP_CelShader并打开它。

要将材质转换为后期处理材质,你需要改变它的材质域。进入“细节”面板,并且修改材质域后期处理

unreal-engine-cel-shading-08

创建卡通着色器的第一步是计算每个像素的亮度,我们称之为亮度缓冲区(lighting buffer)

计算亮度缓冲区

当虚幻将图像渲染到屏幕上时,它将一些通道存储到一些缓冲区中。为了计算亮度缓冲区,你需要访问其中的两个缓冲区:

  1. 后期处理输入:一旦虚幻完成了光照和后期处理,它将把图像存储到这个缓冲区。如果你不进行进一步的后期处理,这将是虚幻向玩家显示的内容。

  2. 漫反射颜色:这是没有任何灯光和后期处理的场景。它将包含屏幕上所有东西的漫反射颜色。

unreal-engine-cel-shading-10

要访问这些缓冲区,你需要在材质蓝图中使用SceneTexture节点。创建一个并选中它,进入“细节”面板。要访问后处理输入缓冲区,将场景纹理ID更改为后期处理输入0

unreal-engine-cel-shading-11

要访问漫反射颜色,创建另一个SceneTexture节点。改变它的场景纹理ID漫反射颜色

unreal-engine-cel-shading-12

亮度缓冲区应该只包含灰度值(描述物体有多亮的)。这意味着你不需要来自两个缓冲区的颜色信息。为了丢弃颜色,将两个SceneTexture节点的Color输出连接到一个Desaturation节点(去饱和度节点)。这将完全去掉这两个缓冲区的饱和度。

unreal-engine-cel-shading-13

要计算亮度缓冲区,只需要用SceneTexture:后期处理输入0除以SceneTexture:漫反射颜色。顺序在这里很重要!

unreal-engine-cel-shading-14

然后,使用Clamp使值保持在0到1的范围内。这使得使用阈值更加容易,因为你可以知道你的可能的值。

unreal-engine-cel-shading-14-1

这里是一个可视化的亮度缓冲区:

unreal-engine-cel-shading-14-2

如你所见,被照亮的区域更接近白色,而未被照亮的区域更接近黑色。

接下来,你将使用亮度缓冲区创建一个阈值。

创建阈值

对于这个卡通着色器来说,任何大于0.5的像素都将使用普通漫反射颜色。小于0.5的像素将使用一半亮度的漫反射颜色。

首先,创建一个If节点,用来比较两个值。然后可以根据比较结果指定不同的输出。

unreal-engine-cel-shading-16

接下来,连接ClampA输入。然后,创建一个值为0.5Constant,并将其插入B输入。

unreal-engine-cel-shading-17

注意:可以通过改变B输入的值来改变阈值。

要获得颜色,需要创建一个SceneTexture节点,并设置它的场景纹理ID漫反射颜色。然后,将Color乘以0.5来得到一个一半亮度的漫反射。

unreal-engine-cel-shading-18

最后,像这样连接所有节点:

unreal-engine-cel-shading-19

总结:

  1. Desaturation节点将后处理输入漫反射颜色转换为灰度图像。

  2. Divide节点来实现后处理输入除以漫反射颜色。这将得到亮度缓冲区。

  3. Clamp节点将使得值保持在0到1的范围内。

  4. If节点使得亮度值大于0.5的像素输出正常漫反射的颜色。如果亮度值小于0.5那么将输出一半亮度的漫反射颜色。

现在你有了卡通着色器,你需要将它应用到场景中。

使用后期处理材质

要使用后处理材料,您需要创建后期处理体积。这些通常用于控制后期处理效果,例如白平衡、饱和度和对比度。

点击应用,然后返回主编辑器。要创建后期处理体积,请转到“放置actor”面板并选择“体积”类别。然后,将一个后期处理体积拖到视口中来创建它。

unreal-engine-cel-shading-20

现在你需要告诉后期处理体积使用卡通着色器。选择后期处理体积,转到“细节”面板。之后,找到“渲染功能/后期处理材质”并点击“+”图标。这将向数组中添加一个新的条目。

unreal-engine-cel-shading-20-1

接下来,点击“选择”下拉框并且选择“资产引用”

unreal-engine-cel-shading-21

这将允许你选择一个材质。点击“无”下拉菜单并且选择“PP_CelShader”

unreal-engine-cel-shading-22

默认情况下,后期处理体积只在相机在它里面时生效。然而,在这个例子中,你希望它影响整个世界。为此,向下滚动到“后期处理体积设置”并且启用“无限范围(未限定)”

unreal-engine-cel-shading-23

现在,卡通着色器被应用到整个图像,你会看到:

unreal-engine-cel-shading-24

“等等,这看起来不像你之前展示的卡通着色器!”

它看起来不同的主要原因是引擎在色调映射之后应用了卡通着色器。为了解决这个问题,你需要告诉引擎在色调映射之前应用卡通着色器。

色调映射之前应用卡通着色器

在向玩家显示图像之前,虚幻会执行一个名为“色调映射”(Tonemapping)的过程。色调映射的一个原因是让图像看起来更自然。它的工作原理使:取一个输入颜色,然后使用曲线将它转换成一个新值。

下面是两个后处理输入缓冲区的图像。一个在映射前,一个在映射后:

unreal-engine-cel-shading-25

如你所见,色调映射前的高光太亮了。然而,在色调映射后,明亮的区域变得更加柔和。

色调映射在大多数情况下是好的。但是,由于在计算中使用的是“后期处理输入”缓冲区,因此需要它的原始值。

打开PP_CelShader,并且确保你没有选择任何东西。然后,转到“细节”面板并找到“后期处理材质”部分。将“可混合位置”设置为“色调映射前”

unreal-engine-cel-shading-26

点击“应用”,然后返回主编辑器。颜色现在看起来好多了!

unreal-engine-cel-shading-27

在下一节中,你将学习如何只对特定对象应用卡通渲染。

隔离卡通着色器

要隔离后期处理效果,需要使用自定义深度(Custom Depth)功能。就像“后期处理输入”和“漫反射颜色”一样,这是一个你可以在后期处理材料中使用的缓冲区。

在你学习什么是“自定义深度”之前,你应该知道场景深度缓冲是什么。“场景深度”存储了每个像素距离相机平面的距离。下面是“场景深度”的展示:

unreal-engine-cel-shading-28

“自定义深度”存储了相同的信息,但只针对你指定的网格。这里是一个将viking模型渲染到“自定义深度”的展示:

unreal-engine-cel-shading-29

通过比较“场景深度”和“自定义深度”,你可以将卡通效果和逼真效果隔离开。如果“场景深度”小于“自定义深度”,则使用普通图像。如果“场景深度”大于“自定义深度”,使用卡通着色的图像。

第一步就是渲染viking模型的“自定义深度”。

使用自定义深度

进入世界大纲视图并选择SK_Viking。然后,转到细节面板并找到“渲染”部分。接下来,启用“渲染自定义深度通道”

unreal-engine-cel-shading-30

接下来,你需要进行深度比较。打开PP_CelShader并创建以下设置:

unreal-engine-cel-shading-31

注意“Mask (R)”节点是“Component Masks”。它允许你将多通道数据转换为标量。你需要屏蔽场景深度和自定义深度的原因是If节点只接受AB输入的标量。

然后,连接卡通着色网的输出到A > B。最后连接If节点里你刚刚制作成“自发光颜色”的输出。

unreal-engine-cel-shading-32

现在,只有渲染到自定义深度的网格将有卡通着色效果了。

点击“应用”,然后返回主编辑器。你会看到现在只有viking模型有卡通着色效果了。

unreal-engine-cel-shading-33

卡通着色器工作得很好,但它有点简单。如果你想要两个以上的色带呢?如果你想在色带之间创造一个柔和的过渡呢?你可以通过使用查找表(LUT)来实现这一点。

什么是查找表(LUT)?

你小的时候,学过乘法是什么。然而,那时候太小了,你的头脑可能无法进行这些计算。你可以用乘法表来“查找”答案,而不是计算。

unreal-engine-cel-shading-34

这就是LUT的本质。它是一个可以通过输入访问的值数组(通常是预先计算的)。在乘法表的例子中,输入是乘数和被乘数。

在这个卡通着色器的上下文中,LUT是带有某种梯度的纹理。以下是四个LUT的示例:

unreal-engine-cel-shading-35

目前,计算阴影颜色的方法是将漫反射颜色乘以常量0.5。这里将使用LUT中的一个值,而不是乘以常量0.5。通过这样做,你可以控制色带的数量和它们的转换。你可以通过LUT的外观来知道如何着色的。

在使用LUT之前,你需要更改它的一些纹理设置。

改变LUT设置

打开Textures文件夹并且打开T_Lut_01。这是LUT的样子:

unreal-engine-cel-shading-36

需要更改的第一个设置是sRGB。当渲染时,虚幻将会把所有启用了sRGB的纹理转换为线性颜色。基本上,这使它更容易为虚幻执行渲染计算。

sRGB设置对于表示外观的纹理来说很好。然而,像法线贴图和LUT这样的纹理,保存了用于数学计算的值。因此,虚幻应该保证它们的值是正确的。通过禁用sRGB,虚幻将不会执行颜色空间的转换。

为此,取消sRGB的复选框。你可以在“纹理”部分找到这个设置。

unreal-engine-cel-shading-37

你需要改变的下一个设置是纹理平铺的方式。因为你没有显示这个纹理,所以没有必要平铺它。此外,启用平铺将在贴图边缘采样时产生问题。例如,因为选了平铺,如果你从贴图的左边缘采样一个像素,它将尝试混合到贴图的右边缘。

要禁用平铺,请将“X轴平铺法”改为“限制”。对“Y轴平铺法”也做同样的操作。

unreal-engine-cel-shading-38

设置完毕。现在你需要在后期处理材质中使用LUT。

使用LUT

关闭T_Lut_01,打开PP_CelShader。首先,删除高亮显示的节点:

unreal-engine-cel-shading-39

接下来,创建一个“Texture Sample”并且将“纹理”修改为“T_Lut_01”。这个LUT将创建三个带有软过渡的色带。

unreal-engine-cel-shading-40

如果你还记得,LUT使用输入来确定要输出哪个值。本例里将使用亮度缓冲区作为输入。

要做到这一点,需要连接Clamp节点到Texture Sample节点的UVs

unreal-engine-cel-shading-41

这是因为亮度缓冲和纹理坐标都在0到1的范围内。例如,如果亮度缓冲区中的像素为0.5,LUT将从纹理的中间输出像素值。

接下来,你需要将漫反射颜色与LUT相乘。为此,重新创建以下设置:

unreal-engine-cel-shading-42

Append节点的目的是将Texture Sample节点的输出转换为四个通道的矢量。这样做是因为你不能用一个三通道向量乘以一个四通道向量(SceneTexture)。

最后,像这样连接所有节点:

unreal-engine-cel-shading-43

现在,不是漫反射颜色乘以一个常数,而是乘以LUT的一个值。它控制了有多少色带以及它们的转换(取决于LUT)。而亮度缓冲区决定了LUT输出的值。

点击“应用”,然后关闭PP_CelShader。卡通着色现在拥有三个色带了,色带之间的过渡也更加柔和。

unreal-engine-cel-shading-44

下面是对所有可选LUT的比较。这些LUT也包含在项目中了。

unreal-engine-cel-shading-45

接下来干什么?

你可以在这里下载完整的项目。

如你所见,后期处理材质是非常强大的。它们允许你创建许多逼真和风格化的效果。如果你想了解关于后期处理的更多信息,请查看后期处理效果文档。


Similar Posts

评论