终末地人物卡通渲染(UE5)复刻笔记

本文由多篇零散笔记合并整理而成,包含皮肤、面部、眉毛、眼部、头发、衣服与刘海阴影七大部分的材质搭建流程。

前言

这次渲染学习是跟着 B 站「虚幻次次」的教程做的。教程整体偏效果向,并没有完全严格地按照终末地官方的渲染方式来还原,其中也有一些贴图没有用到,比如 ramp 贴图lut 贴图。这两块先不深入,等后面自己尝试复刻洛克王国渲染的时候再回来详细解释。

用 UE 做材质,省去了很多光照的基础计算,节点式的搭建方式也更好理解;不过看别人的节点图时,如果又乱又多,理解起来还是比较麻烦。

在此之前我在 Unity 里有过一些 NPR 渲染经验,但比较浅。这次回到 UE 并没有想象中顺利,只是简单地在引擎端把效果大体复刻了出来,还没有深入到贴图的制作规范上。不过有了这个基础,相信后面要深入做的洛克王国渲染,能好好写出一篇文章。

通用基础

各个部位的材质有不少共通的技巧,先集中说明,后面就不再重复。

1. 着色模型与混合模式

角色身上的材质几乎都使用无光照着色模型,混合模式根据部位选择“不透明”或“半透明”。最终颜色不走光照计算,而是直接输出到自发光(Emissive)引脚,把 PBR 光照的影响降到最低,得到更可控的卡通效果。唯一的例外是皮肤,为了改善阴影,把着色模型改成了次表面轮廓

2. 贴图采样与颜色空间

  • 颜色贴图用 Texture Sample 采样时保持 SRGB(为什么用 SRGB?[[颜色空间、伽马映射]]);法线贴图则要取消 SRGB
  • 采样出的 RGB 值通常先做 Power 处理(相当于“色调映射 / 对比度增强”,幂值不同效果不同),再用 Saturate 压回 0-1,最后与一个颜色参数正片叠底,方便美术微调整体色调。
  • 终末地是在 Unity 中制作的,法线贴图是 Unity 坐标系,解压前要把 G 通道翻转;法线的第三个分量(Z)不需要额外存储,用 UE 自带的 DeriveNormalZ 节点解压即可([[法线贴图]])。

3. 常用节点与材质函数

  • MF_Adjust:一个通用的“缩放 + 偏移”调整函数,几乎所有的遮罩和数值都可以套它来微调。例如把 AO 除以 AOSmooth 做整体缩放,再减去 AOOffset 做整体平移。
  • Flatten Normal:把法线往切线空间 Z 轴方向“掰”,用来控制法线强度、压低凹凸感,让阴影更平、更贴合卡渲观感。
  • BlendAngleCorrectedNormal:对两个切线空间法线做角度矫正混合(内部会转到世界空间插值再转回)。简单理解就是基础法线定大局、附加法线做微调:基础法线指哪,结果大致就在那个方向;附加法线在此基础上施加一个“偏移力”。基础法线越平,偏移越弱;基础法线越斜,细节纹理的“扭动感”越明显。
  • ParallaxOcclusionMapping:视差遮挡映射,用于生成带透视效果的采样 UV(见 [[法线贴图]] 中的视差遮挡映射部分)。
  • DepthFade:按模型到后方物体的距离输出 0-1,常接到不透明度上做半透明过渡。
  • sphereMask:球形遮罩,这里用于模拟点光源的受光范围。

4. 常用光照与遮罩

  • Lambert:法线与光照方向的点积(记得归一化),作为受光遮罩,避免背光处出现不合理的亮度或高光([[光照模型]])。
  • GGX 高光:用 UE 的 GGXSpecular 节点,输入 Normal、LightVector、Roughness,其中 Roughness = 1 - Glossiness([[GGXSpecular]])。
  • MatCap:按 MatCap 原理计算 matcap_UV,采样 MatCap 贴图得到高光([[MatCap]])。
  • Rim 边缘光:视角向量与法线向量点乘后翻转,边缘值接近 1,做成边缘遮罩。
  • AO 混合:AO 作为 α,在 AOColorBaseColor(或两者正片叠底后的颜色)之间 lerp,控制环境光遮蔽的强弱([[AO、环境光遮蔽]])。

一、皮肤渲染

皮肤使用无光照着色模型。

1. BaseColor

  1. 采样 SRGB 皮肤贴图,把 RGB 值作为指数底数做 Power(幂值暂时取 1),用于色调映射和对比度增强。

Pasted image 20260705210756.png

  1. Saturate 压回 0-1,再与颜色参数正片叠底,方便美术调整整体效果。
  2. 皮肤贴图的 A 通道是 AO:单独提取后除以 AOSmooth 做整体缩放,再减去 AOOffset 做整体平移,让 AO 的强弱更可控。

2. 压掉 PBR 感

如果直接把 BaseColor 接到材质输出,皮肤的 PBR 效果会很明显。根据迪士尼 BRDF([[BRDF知识点整理]])的思路——它不追求物理精确,只求“看起来对”——用 4 个浮点参数 MSRE = (0, 1, 1, 0) 分别控制金属度、高光度、粗糙度、自发光,与 BaseColor 相乘,把 PBR 感压下去。

3. 阴影调整(次表面轮廓)

直接看皮肤,阴影部分会死灰死灰的,非常难看。解决办法是把材质的着色模型改为次表面轮廓UE 官方文档),它可以控制次表面照明的散射距离、次表面颜色和离开对象后的衰减色,皮肤阴影会好看很多。

要注意这直接使用 UE 自带着色模型,开销比较大,想要更高性价比就得改引擎源码。另外还需要给皮肤材质属性加上不透明度,修改不透明度也能微调效果。

4. Normal Blend

改成次表面轮廓后,PBR 感会进一步增强,导致卡渲程度不够。这里通过调整顶点法线来解决:

  • 使用 Vertex Normal WS(终末地模型顶点多,效果更好,且顶点法线开销比面法线小)、Camera VectorSkyAtmosphereLightDirection 三个向量,都先转换到切线空间并归一化([[切线空间,其他空间]])。
  • 用 Flatten Normal 分别调整 Camera 方向和光照方向的法线强度。
  • 再用 BlendAngleCorrectedNormal 混合,控制阴影的平滑度。直观理解:Camera 强度调得越大,最终法线越偏向视角方向,阴影就越平、越符合 NPR 的效果。

5. Rim 与 AO

  • Rim:Camera 与 Vertex Normal 点乘后翻转,边缘接近 1,再过 MF_Adjust 作为 lerp 的 α。两种混法都行:BaseColorRimColor 直接 lerp;或 BaseColor 与“BaseColor × RimColor 正片叠底”的中间色 lerp。
  • AO:把加完 Rim 的颜色作为输入,反过来用 AO 作 α,用同样的混合方式再叠一层,得到最终皮肤的 BaseColor。

二、面部渲染

面部使用无光照着色模型。

1. 基础颜色

同样直接采样基础贴图做 Power,和前面的流程一致。另外基础贴图的 A 通道带有鼻尖阴影的 AO,可选加上;不过后续做 SDF 阴影时发现,鼻尖阴影和 SDF 阴影的配合比较差,需要取舍。

2. 嘴唇高光

嘴唇高光有 GGX、MatCap、直接采样高光贴图等多种做法,GGX / MatCap 都需要一个遮罩来圈定嘴唇区域(除了遮罩贴图,也可以看模型的顶点色)。这里采用直接采样嘴唇高光贴图的方式。

有个关键现象:嘴唇高光会随着视角左右移动,但不会随上下移动,所以视角偏移时 UV 也要跟着偏移。偏移量用人物右方向向量 × 视角向量得到,再乘缩放系数(这里用 0.01,可按实际效果调整)。

3. 边缘颜色渐变(伪 SSS)

边缘颜色渐变能给脸部带来一种伪次表面散射的效果。遮罩取自遮罩贴图的 R 通道,遮罩值乘边缘颜色后,用叠加(Add)混合加到基础颜色上。

4. SDF 阴影

面部阴影直接用 SDF 实现([[SDF技术]]):提取 SDF 信息后与 BaseColor 做颜色混合,调用之前写好的颜色混合材质函数即可,具体用法详见《SDF 基础》。

三、眉毛渲染

眉毛使用无光照着色模型 + 半透明混合模式。

1. 基础颜色

和前面一样:采样基础颜色贴图 → Power → Saturate。

2. 眉毛透视处理

  • 眉毛透视的做法是把模型沿 Camera 方向做顶点位置偏移,偏移量用参数手动调节。
  • 眉毛与头发重叠的部分,用 DepthFade 调节:该节点会检测模型到后方物体的距离,在设定的距离范围内输出 0-1,接到不透明度重载上,让重叠处自然过渡。

四、眼部渲染

眼部使用无光照着色模型 + 不透明混合模式。

1. 视差遮挡映射(眼睛透视的核心)

眼睛的透视感是通过 ParallaxOcclusionMapping(视差遮挡映射) 节点生成的特殊 UV 来采样贴图实现的。

Pasted image 20260722105925.png

以陈千语的眼睛贴图为例(其 Alpha 通道带有高光 mask,很适合讲解):

  • 高光部分和 BaseColor 部分用不同的视差遮挡映射生成不同 UV,分别采样,再用 Alpha 值做线性插值。
  • 高度图的 B 通道给 BaseColor 用,G 通道给高光用,其他引脚没有区别。
  • 高度图的 R 通道就是高光贴图:用高光的 UV 采样后,与前面的高光相加,再加到 BaseColor 上;中间记得乘一个浮点参数,方便调整强度。

五、头发渲染

头发使用无光照着色模型。

1. 美术资产

原笔记此节未展开,主要关注基础色、两层高光与点光源三部分。

2. 基础颜色

采样头发贴图 RGB → Power → Saturate,再分别叠加 Lambert_ShadowAO_Shadow 两个遮罩,最后路由到 BaseColor。

3. 高光

头发用两层高光:一层 MatCap 高光,一层各向异性高光(Kajiya-Kay 模型,[[各向异性渲染:Kajiya-Kay、Anisotropic GGX、Marschner三大模型]])。

  • MatCap 高光:流程和衣服部分一致,采样后记得叠加各种 Mask。
  • Kajiya-Kay 各向异性高光:从终末地头发的 UV 分布看,头发走向是 V 方向,在切线空间里就是副切线方向(Y 轴),所以用法线与 (1, 0, 0) 叉乘得到切线。终末地贴图里有法线偏移来制造错乱感,把它作用到法线上即可间接影响结果;另外可以配合球形法线映射([[球形法线映射]]),让“天使环”不会错开太多。
  • 计算出的切线代入 Kajiya-Kay 公式后,结果还要过一系列 Mask:除了 AO、Lambert,还需要 RimMaskTopStep,后者用于把高光的上部截断。做法是拿原始切线与 H 点乘,结果接 SmoothStep,min 取 0.02(上部截断值),max 取“0.02 - 渐变值”。Kajiya-Kay 输出的是 √(1 - HoT²),0.02 往上的区域 HoT 逐渐变大;这里 SmoothStep 的 min > max,方向反了:大于 min 输出 0,小于 max 输出 1,中间渐变,从而实现上部截断。

4. 点光源

点光源直接用 sphereMask 球形遮罩节点即可。

Pasted image 20260717154033.png
Pasted image 20260717154131.png

5. 汇总输出

最后把 BaseColor、两层高光和点光源叠加,输出到自发光引脚。

六、衣服渲染

衣服使用无光照着色模型。

1. 基础颜色

从贴图提取 RGB → Power → Saturate → 与 BaseColor 参数正片叠底。

2. 褶皱

衣服的褶皱有 4 种来源:

  1. 基础贴图自带阴影:直接赋上 BaseColor 就能看到轻微褶皱,说明褶皱画在基础贴图里了,不用额外处理。
  2. 法线贴图:衣服法线贴图的 RG 通道有数值。采样前要在贴图设置里取消 SRGB;解压用 DeriveNormalZ(Unity 坐标系,先翻转 G 通道)。得到法线后与皮肤一样,用 Flatten Normal 控制强度,再与视角方向、光照方向做 BlendAngleCorrectedNormal 混合,控制阴影平滑度。
  3. AO 贴图:皮肤的 AO 在基础贴图 A 通道,衣服的 AO 在 _P 贴图的 B 通道,采样出来后同样用 MF_Adjust 调整。
  4. 模型自带凹凸:终末地衣服模型并没有自带凹凸,跳过。

混合方式:法线直接接到材质属性的 Normal 节点;AO 则是把 AOColor 与 BaseColor 正片叠底,再与 BaseColor 用 lerp 混合,AO 作为 α。

3. Rim

和皮肤相同的流程:视角向量与法线点乘 → 翻转 → MF_Adjust 调整 → 作为 lerp 的 α。法线可以选法线贴图的法线,也可以选顶点法线;混合方式与 AO 一致。

4. 光照处理

  • Lambert:作为受光遮罩,处理顺序放在 AO 叠加之前,混合方式与 AO 一样。
  • GGX 高光:用 GGXSpecular 节点,Normal 用法线贴图(Flatten Normal 控强度);LightVector 用 CameraVectorSkyLightDirection 相加后,再与 SkyLightDirection lerp、归一化(α 用参数控制);Roughness = 1 - Glossiness(测试发现 _P 贴图 A 通道就是光泽度)。输出要乘几个遮罩:AO 和金属度(测试发现 _P 贴图 R 通道就是金属度),遮罩强度用 lerp 控制,再套 MF_Adjust。最后最好再乘一个 Lambert 遮罩,避免背光处出现高光,并截断到 0-1。
  • MatCap:按原理计算 matcap_UV 采样贴图,采样值叠加颜色参数后,通过 AO 和 Lambert 遮罩输出。注意混合顺序:MatCap 在 GGX 高光之前加到 BaseColor 上。

七、刘海阴影

刘海阴影使用 HairShadow 网格体,无光照着色模型 + 半透明混合模式,有两个需求:

  1. 阴影映射背后颜色:用 SceneColor 节点提取模型背后像素的颜色(需要输出 Screen Position),转 HSV 后通过 Float3 参数调色([[颜色空间、伽马映射]]),再转回 RGB,乘以 Shadow_Color,接到自发光引脚。
  2. 背后无物体时不投射阴影:用 SceneDepth 判断。把 SceneDepth 除以 500(数值自取),Saturate 截断到 0-1:背后无物体的地方输出为 1,OneMinus 后再乘不透明度参数,这样只在有背景的地方生成阴影,没有阴影的区域结果恒为 0。最后接到不透明度重载。

结语与后续计划

总的来说,这次跟着教程把终末地角色卡渲在 UE 引擎端大体复刻了一遍,收获不小:

  • 无光照模型 + 自发光输出,是这套材质去 PBR 化的核心思路;
  • 法线、AO、Rim、Lambert、GGX、MatCap 这些遮罩的层层混合,构成了各个部位最终的效果;
  • 还没有深入贴图制作规范(ramp、lut 等贴图本次也没用到)。

接下来的计划:先了解 PBR 内容,再学习 RenderDocDCC 与工具,然后是洛克王国渲染复刻(放在 RenderDoc 学习之后)和喜欢的材质复刻

标签: none

添加新评论