原文|《Unreal Engine 4 Cel Shading Tutorial》
作者|Tommy Tran Feb 27 2018
阅读时长|20分钟 内容难度|中等

文章目录

  • 开始吧
  • 什么是卡通着色?
  • 卡通着色原理
  • 创建卡通着色器
    • 计算光照缓冲
    • 创建阈值
  • 使用后期处理材质(Post Process Materials)
  • 在色调映射之前应用卡通着色器
  • 孤立卡通着色器(Isolating the Cel Shader)
    • 使用自定义深度
  • 什么是查找表(Lookup Table 即 LUT)
    • 修改LUT设置
  • 使用LUT
  • 接下来干什么

基于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从而获得亮度减半的漫反射颜色值。

最后,如下连接所有的节点:


小结:

  1. Desaturation节点将把Post Process InputDiffuse Color转换成灰度图像
  2. Divide节点将Post Process Input除以Diffuse Color,是我们获得光照缓存。
  3. Clamp节点是出数值介于0到1之间。
  4. 使用If节点,使光照值高于0.5的像素输出正常颜色,使小于0.5的像素输出亮度减半的颜色。

这样你就得到了你的卡通着色器,你需要把它应用到场景中。

使用后期处理材质(Post Process Materials)

我们需要创建一个叫做后期处理体积(Post Process Volume)的东西,才能使用后期处理材质。 后期处理体积常用于控制诸如白平衡(white balance)、饱和度(saturation)以及对比度(contrast)等后期处理效果。

点击Apply然后主编辑器。在模式面板(Mode Panel)的体积(Volumes)分类中找到后期处理体积(Post Process Volume),然后将它拖拽入视口。


接下来,需要告诉后期处理体积使用卡通着色器。先选择后期处理体积,在其细节面板上找到Rendering Features\Post Process Materials并点击+号标记。
然后点击名为Choose的下拉菜单并选择Asset Reference

然后点击当前显示None的下拉菜单,选择之前创建的“PP_CelShader”材质。

默认情况下,后期处理体积只会影响其范围内的对象,但本例中,我们想让它影响这个世界,所以要启用它的Infinite Extent (Unbound)选项。

这样,卡通着色器就被应用到了整个画面,你将看到下图的样子:


“等等!这看起来和你最初展示的卡通着色并不时很像哦!”

这个区别的主要原因是引擎是在色调映射(tonemaping)之后应用的卡通着色器。要修正这个问题,我们需要让引擎在色调映射之前应用卡通着色器。

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

在显示一幅画面之前,虚幻引擎需要进行一个叫做色调映射(tonemaping)的处理。它的作用是让画面看起来更逼真。其实现原理是将输入的颜色通过曲线转换成新的值。

下面是两幅后处理输入缓冲的图像。一个是色调映射前的一个是色调映射后的:


如你所见,色调映射前高光部分太亮了,而色调映射后高光区柔和了很多。

色调映射在多数场合都表现良好。但因为我们要对后处理输入缓冲进行重新计算,所以我们需要它的原始值。

打开PP_CelShader并确认你没有选择任何东西,然后再其细节面板找到Post Process MaterialBlendable Location 设为Before Tonemapping

点击应用并回到主编辑器,这时颜色看起来好多了。


在下一个部分,你将学习如何将卡通着色应用到特定的对象。

孤立卡通着色器(Isolating the Cel Shader)

我们需要使用一种叫做自定义深度(Custom Depth)的特性来孤立后处理效果。如同Post Process InputDiffuse Color一样,自定义深度也是一个可以在后处理材质中访问的缓冲。

在学习自定义深度之前,我们先来了解一下什么是场景深度(Scene Depth)缓冲。场景深度存储着每个像素距摄像机平面的距离。下图是一个可视化的场景深度图:


自定义深度存储着同样的信息,只不过它只针对你指定的模型存储。下图是这个维京模型的可视化自定义深度图:


通过对比场景深度和自定义深度,我们可以将效果孤立出来。如果场景深度低于自定义深度,则使用普通画面,如果场景深度高于自定义深度则使用可通着色画面。

首先用自定义深度渲染维京模型。

使用自定义深度

在世界大纲( World Outliner)中选择SK_Viking,然后再细节面板找到Rendering部分,启用Render CustomDepth Pass

接下来进行深度对比。打开“PP_CelShader”并创建下面的节点连接:

注意: Mask (R)节点是组件遮罩。它们可以将多个通道数据转换成标量。之所以要对场景深度和自定义深度进行遮罩,是因为If节点的A和B只能接受标量。

接下来,进行如下连接:

现在只有在自定义深度中渲染的模型才可以获得卡通着色了。

点击应用并回到主编辑器,你会看到只有维京人模型有卡通渲染:


这个卡通着色器效果不错,但是还有点太简单。比如,如果我们想要多于2个段的色彩怎么办?如果我们想在段与段之间创建一些柔和的过渡怎么办?我们可以使用查找表(Lookup Tables 即LUT)来实现这一需求。

什么是查找表(Lookup Table 即 LUT)

我们小时候刚学乘法时,每人都会背诵乘法表。当计算乘法题时,与其说是计算,不如说是在乘法表中查找答案。


这个乘法表本质上就是一个查找表(LUT)。它是一个可以通过输入值查找预计算的数组。在乘法表中,输入值就是乘数和被乘数。

在卡通着色器中 LUT就是一个拥有一些渐变的图片。下图就是LUT的大致长相:

之前我们计算暗部颜色是通过漫反射色乘以0.5。接下来我们不再让它乘以常数0.5,而是使用LUT中的值。这样你可以灵活地控制段数和过渡。通过LUT的样子,你可能已经想到着色时如何查找它了。
在使用LUT之前,我们需要对它的纹理设置做一些修改。

修改LUT设置

在“Textures”文件夹中找到“T_Lut_01”。这个就是LUT的样子:

第一个需要修改的设置是sRGB。在渲染过程中虚幻引擎会将所有启用sRGB的纹理转换成线性颜色。这样更便于引擎进行渲染计算。

sRGB设置对那些要用于显示的纹理非常有益的,但是对于法线贴图以及LUT等存储数值并用于数学计算的纹理就不行了。因此应该停用sRGB,使虚幻引擎不再对这些纹理进行转换。

在纹理区取消sRGB的勾选。

另外一个需要设置的是纹理的瓦片化。因为我们并非要显示这个纹理,所以没有必要对其瓦片化。并且如果依旧保留其瓦片化的勾选将会导致其边缘抽样时的一些问题。

将其X-axis Tiling MethodY-axis Tiling Method都设置为Clamp

将这些设置完毕,我们需要将LUT应用到后处理材质中。

使用LUT

关闭“T_Lut_01”并打开“PP_CelShader”。首先删除下图中高亮的节点:


然后创建一个Texture Sample节点并将其Texture设置为“T_Lut_01”。这个LUT将会产生3个带有柔和过渡的色段。

还记得么?LUT需要依据输入值来决定输出值。本例中我们将使用光照缓冲作为输入值。

Clamp节点连接到Texture Sample节点的UVs上。

因为光照缓冲和纹理坐标的值域都是0到1,所以这样的连接是可行的。比如纹理缓冲中的某像素值为0.5,那么LUT的输出值将为纹理中间的值。

接下来,我们通过下图所示重新连接节点来实现漫反射色和LUT的相乘:

之所以要用Append节点将Texture Sample 节点的输出转换为4维向量。因为3维向量无法和4维向量(场景纹理)相乘。

最终,节点连接图如下所示:

现在,我们不再让漫反射色和常量相乘,取而代之,让它乘以一个LUT的值。这样就可以用LUT来控制色段的数量以及它们之间的过渡。光照缓冲将决定LUT的输出。

点击应用并关闭“PP_CelShader”。此时,卡通着色将有3个带柔和过渡的色段。


下面是使用不同LUT获得效果的对比。这些LUT也包含在项目中。

接下来干什么

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

如你所见,后处理材质相当强大。它们可以让你创建很多逼真的以及风格化的效果。

Unreal Engine 4 卡通着色(Cel Shading)教程相关推荐

  1. Unreal Engine 4 卡通轮廓线(Toon Outlines)教程 之 后期处理法(Post Process Outlines)

    本文是<Unreal Engine 4 卡通轮廓线(Toon Outlines)教程>的第二部分:后期处理法(Post Process Outlines),书接上文<Unreal E ...

  2. 【学习笔记】Unreal Engine 4 虚幻引擎蓝图中级教程物理碰撞教程

    教程链接:Unreal Engine 4 虚幻引擎蓝图中级教程物理碰撞 想共享的小伙伴可以E-mail我:lxbcolorgalaxy@qq.com 目录 第一章 常见的物理现象及分析 1蓝图模板中的 ...

  3. Unreal Engine 4 卡通轮廓线(Toon Outlines)教程 之 反转网格法(Inverted Mesh)

    原文|<Unreal Engine 4 Toon Outlines Tutorial> 作者|Tommy Tran Apr 2 2018 阅读时长|25分钟 内容难度|入门级 文章目录 开 ...

  4. ArcGIS Maps SDK for Unreal Engine通过UI方式显示地图教程

    前言 一个 UE 项目,可以包括多个关卡(level),关卡可以在菜单栏中新建(文件->新建关卡). 使用快捷键 Ctrl+S 可以保存当前关卡,你可以保存到上面提到的演示文件放置的位置,你可以 ...

  5. Unreal Engine 4(UE4)下载教程

    首先登陆到UE官方网站https://www.unrealengine.com  下载EpicGamesLauncherInstaller-2.1.3-2533468.msi文件 按照提示进行安装 如 ...

  6. Unreal Engine 4 使用HLSL自定义着色器(Custom Shaders)教程(下)

    本文是<Unreal Engine 4 自定义着色器(Custom Shaders)教程>的下半部分,上半部分请见<Unreal Engine 4 自定义着色器(Custom Sha ...

  7. Unity Toon Shader 卡通着色器(一):卡通着色

    一直对非真实感渲染 (Non-Photorealistic Rendering) 很感兴趣,正好发现某社出的新游戏中可以选择真实质感或卡通质感,所以想试试在 Unity 里实现一下卡通着色器. 卡通渲 ...

  8. Unreal Engine 4 手绘风滤镜(Paint Filter)即 桑原滤镜(Kuwahara Filter)教程(上)

    原文|<Unreal Engine 4 Paint Filter Tutorial> 作者|Tommy Tran May 1 2018 | 翻译 开发游戏的老王 阅读时长|25分钟 内容难 ...

  9. ue4 离线渲染_[译]Real Shading in Unreal Engine 4(UE4中的真实渲染)(2)

    利用假期接着把剩下的部分搞完吧,其实,纯粹的翻译应该还是比较简单的,但是,为了更好地理解,我一般都会多找一些资料来进行互相印证.在上面一部分Shader Model的改变过程中,我主要是参考了一些PB ...

最新文章

  1. 刘强东的代码水平到底有多强?30年前就已破万!
  2. 交大c语言第二次作业答案,C语言程序设计第二次作业题及答案.doc
  3. 2010年5月八达岭野生公园 51CTO老虎围观团强力插入
  4. 关于asp.net中链接数据库的问题
  5. 2019河南对口高职高专计算机,2019年河南普通高招最后一个批次 高职高专批正式投档...
  6. HDR 成像技术学习(二)
  7. [转]ASP.net(c#)生成条形码
  8. JS删除两个数组中相同的某个对象值
  9. 百度二年级手工机器人_使用盈首AI炒股机器人,能获得超高超额收益率
  10. class AT where T:new()相关知识点
  11. WPF 使用附加属性增加控件属性
  12. mysql中url的格式_MySQL JDBC URL中的格式以及参数介绍
  13. 基于JAVA获取行政区边界坐标_基于JavaScript实现高德地图和百度地图提取行政区边界经纬度坐标...
  14. 3.2、如何通过JLINK下载程序(附JLINK驱动)
  15. brctl: command not found
  16. DSP 2812: 使用C++封装SCI
  17. LeapFTP3.1注册码
  18. 宝马冷却系统及电动冷却液泵部件(电子水泵)功能特性及标准
  19. Spring全家桶简介
  20. [angular1.6]Error: transition superseded ui-router 在angular1.6 报错误问题解决

热门文章

  1. js之escape函数
  2. android 快传 源码_安卓APP仿茄子快传源码,Android项目源码类似茄子快传的快传项目包括服务端...
  3. vuex--热更替配置
  4. block的名词形式_block是什么意思?
  5. 什么是边缘人工智能和边缘计算?两者有什么联系?
  6. 中国汽轮机及辅机制造发展状况与经营效益预测报告(2022-2027年)
  7. 广西人工智能学会第一次会员代表大会召开
  8. PCB中电流与线宽 电流与过孔的关系
  9. 《BitUp》:像素风格游戏及地图编辑器的开发历程
  10. 淘宝内部员工购物通道