原文|《Unreal Engine 4 Cel Shading Tutorial》
作者|Tommy Tran Feb 27 2018
阅读时长|20分钟 内容难度|中等
基于PBR渲染在Unreal Engine 4中制作写实风格的游戏是比较容易的。PBR渲染会模拟光照和材质的交互并生成最终结果。然而如果想开发风格化效果的游戏,你可能就要探索其它技术了。
其中一种技术叫做卡通着色(英文名:Cel Shading 或 Toon Shading)。这种技术就是模仿典型卡通或者动画中的着色风格。比如《街头涂鸦》(Jet Set Radio)或者《塞尔达传说 之 风之杖》(The Legend of Zelda: The Wind Waker and Gravity Rush)
在本教程中,你将会学到:
- 如何创建和使用后期处理材质
- 创建卡通着色器
- 将卡通着色器应用于特定的模型
- 使用查找表(LUT:Lookup table)控制色带(color band)
注意:本文假设你已经有了一定的UE4基础知识
注意: 本文是Unreal Engine着色器教程四部曲之一:
- 第一部分: 卡通着色(Cel Shading)
- 第二部分:卡通风轮廓线(Toon Outline)
- 第三部分:使用HLSL自定义着色器(Custom Shaders Using HLSL)
- 第四部分:绘画风滤镜(Paint Filter)
开始吧
可以先下载初始工程,打开压缩包中的CelShader.uproject,你就可以看到下面的场景了:
我们将对这个角色使用卡通着色。在开始之前,你要知道什么是卡通着色。
什么是卡通着色?
卡通着色就是使用一个多端的色带来渲染对象,而非使用连续的梯度。
下面就是塞尔达传说之旷野之息中的卡通着色。注意:只有角色是卡通着色,背景并不是。
上图中,有3个色段。一个影区色段,一个中间区色段,一个高光区色段。
有一个常见的误解,即有轮廓线就是卡通渲染。可以将无主之地(Borderlands)作为一个反例。尽管这个游戏是风格化的,但它不是卡通渲染。参见下图,注意角色的渲染并非使用色段:
尽管轮廓线并非卡通渲染的一部分,但它们经常被一起使用。因为这样画面会更像手绘的。参见类似
龙珠战士Z(Guilty Gear Xrd and Dragon Ball FighterZ)
在下个部分中,你将学习如何实现卡通渲染。
卡通着色原理
最常用的方法就是比较表面方向(即法线方向)和光照方向。通过计算法线和光线的点积,你可以获得一个介于-1和1之间的值。
当值等于-1,说明表面和光线朝向反向;0说明二者垂直;1说明二者朝向相同。
为点积设定阈值,可以定义多个色带。比如,可以将暗色指定为点积大于-0.8.当点积低于-0.8即为亮色。这样就定义了两个色段。
这种方法的局限性在于:
- 其它的光源将不能影响卡通着色对象
- 其他物体也无法向卡通着色对象投影
我们需要使用其他方法来修正这些问题。不再计算点积,而是计算表面光照量,然后使用这个值取代点积。
现在你已经知道什么是卡通着色以及它的工作原理,是时候亲手创建一个了。
创建卡通着色器
本文的卡通着色是基于后期处理效果(post process effect)。后期处理允许你在引擎渲染完画面以后对它进行调整。后期处理常用于景深效果(depth of field),动态模糊效果(motion blur)以及光华效果(bloom)。
要创建后期处理效果,你需要使用一种后期处理材质(post process material)。在材质文件夹中创建一个新的材质文件并重命名为“PP_CelShader ”,然后打开它。
将其domain
选项由默认的Material Domain
改为Post Process
,这样就可以将普通材质转换为后期处理材质。
第一步要计算每个像素的光照是多少。我们将其称之为光照缓冲(lighting buffer)。
计算光照缓冲
当虚幻渲染一张图像到屏幕时,它会将批次(pass)存储到一系列缓冲区中。为了计算光照缓存,我们必须访问其中的两个缓冲区
1. 后处理输入(Post Process Input): 一旦虚幻完成了光照和后处理,它会将图像存储到这个缓冲区。如果你不在对它做进一步的后期处理,那么这就是虚幻要显示到屏幕的内容。
2. 漫反射颜色(Diffuse Color:) 这个是没有任何光照和后处理的场景。它将包含屏幕上所有对象的漫反射颜色。
我们需要使用ScreenTexture
节点来访问这些缓冲区。创建并选择该节点,在其细节面板(Details panel)上设置要访问的缓冲区。
- 要访问
Post Process Input
缓冲区,将Scene Texture Id
改为PostProcessInput0
- 要访问
Diffuse Color
缓冲区,将Scene Texture Id
改为DiffuseColor
光照缓冲(lighting buffer)仅包含描述光照量的灰度值。这意味着我们不需要两个缓冲区中的颜色信息。我们可以将两个SceneTexture
节点的颜色输出连接到一个Desaturation
节点(去饱和度节点)来去除颜色信息。这样两个缓冲区的颜色就被完全去除了。
用SceneTexture:PostProcessInput0
除以SceneTexture:DiffuseColor
,这样光照缓冲就很简单地得到了。
然后,使用一个Clamp
节点将输出值限制在0到1之间,这样更方便我们设置(色段的)阈值了。
下图就是一个可视化表示的光照缓冲:
如你所见,光照区偏白色,非光照区偏黑色。下一步,我们就可以使用光照缓冲来创建阈值。
创建阈值
本例中,对于任何像素如果其计算结果大于0.5,则使用正常的漫反射颜色;如果小于0.5将使用亮度减半的漫反射色。
注意: 你可以改变B的输入从而改变阈值
再创建一个SceneTexture
节点,并将Scene Texture Id
改为Diffuse Color
,然后用Color
乘以0.5从而获得亮度减半的漫反射颜色值。
最后,如下连接所有的节点:
小结:
-
Desaturation
节点将把Post Process Input
和Diffuse Color
转换成灰度图像 - 用
Divide
节点将Post Process Input
除以Diffuse Color
,是我们获得光照缓存。 -
Clamp
节点是出数值介于0到1之间。 - 使用
If
节点,使光照值高于0.5的像素输出正常颜色,使小于0.5的像素输出亮度减半的颜色。
这样你就得到了你的卡通着色器,你需要把它应用到场景中。