type
Post
status
Published
date
Jun 2, 2026
slug
zmd1
summary
Cloth
tags
Unity
角色
卡通渲染
category
效果还原
icon
password
0. 前言
学习了一阵子卡通渲染,参考了别的大佬的文章和代码,也终于是做出来一个效果还可以的成品,于是写一篇文章记录一下还原的过程。
代码有点乱还没整理,特殊材质也没加进去,先凑合看。

1. 贴图分析
1.1 Albedo
_Albedo 是基础色贴图。RGB 提供衣服本身颜色,A 通道参与透明相关计算。
1.2 Normal Map
_NormalMap 只有RG通道有信息,shader里面需要自己算一下
1.3 MRO Map
_MROMap 是一张通道打包贴图:- R:Metallic
- G:Specular Scale
- B:Occlusion
- A:Smoothness

1.4 Diffuse Ramp
RGB 和 A 的职责分开:
- RGB:控制漫反射色带
- A:控制亮暗权重

1.5 Specular Ramp
_SpecularRamp 用来重映射高光颜色,Shader 计算 GGX 高光,高光颜色会采样 Specular Ramp。
1.6 CubeMap
_CharCubeMap 用来计算环境高光1.7 Emission Map
_EmissionMap 处理衣服上的发光区域2. Shader 向量准备
2.1 TBN
TBN矩阵,采样NormalMap,处理法向
2.2 ViewDirection
ViewDirection会影响高光、IBL、Rim、BackLight Rim。
2.3 主光方向
主光方向、颜色、亮度
2.4 相机前方向
cameraForward 会参与 Wrap 补光、高光半角向量、Rim 方向和 BackLight Rim 判断。2.5 水平投影与背光关系
cameraLightDot 描述当前镜头和主光在水平面上的关系。相机接近观察背光面时,这个值会升高。3. 漫反射
Diffuse主要思路:
- 虚拟顶光作为环境光
- Ramp Tinted
- WrapLight补光
- BaseColor分层:亮部、暗部、暗暗部
- 根据ao、rampA、shadow来对明暗进行混合
3.1 环境光:虚拟顶光
这里的环境光使用一盏人为设置的虚拟顶光。
对应参数:
相比于SH的环境光,这样做更有体积感?
参考文章里面也有关于这里的解释,也是通过观察游戏里的效果得出的
_VirtualLightParams 对 dot(N, virtualLightDir) 做remap:- Offset:抬高或压低整体受光。
- Scale:控制虚拟光的影响范围。
- Bias:提供最低基础亮度。
然后根据阴影权重混合虚拟光颜色,这里不混合也问题不大
3.2 主光:Ramp 漫反射
主光从
NoL 开始:接着加入相机相关 Wrap Light:
这段逻辑用于处理背光和侧光下的大面积暗面。
cameraLightDot 越高,说明镜头越接近观察背光面;cameraYSmooth 会根据相机俯仰控制补光强度;_RampOffsetWrapBlend 决定 Wrap 参与比例。之后把修正后的
modNoL 映射到 Ramp UV:Ramp RGB 控制色带,Ramp A 进入后面的阴影。
3.3 Shadow
先取 Unity 主光阴影和自定义 PerObject 屏幕空间阴影:
接着用
SigmoidSharp 来获得更可控的阴影边界:最终明暗遮罩:
这里混合了四类信息:
occlusion:MROMap B 通道,控制材质 AO。
rampA:Diffuse Ramp Alpha,控制 Ramp 明暗权重。
shadowScene:Unity Shadow 与 PerObject Shadow 的合成结果。
_ShadowStrength:整体阴影强度。
3.4 Diffuse Color:亮部、暗部与深暗部
得到
minShadow 后,先构建三层基础漫反射颜色:三层颜色分别对应亮部、普通暗部、深暗部。
深暗部会再做一次亮度和饱和度修正:
然后通过视角阴影和 Ramp A 混合暗部层次:
再通过
minShadow 从暗部过渡到亮部:接着把 Ramp RGB 乘进去:
这里先计算 Ramp 的色度。Ramp 色彩越明显,对漫反射颜色影响越强;Ramp 越接近灰阶,对底色影响越弱。
Ramp 改色后会做亮度补偿:
这一步用原本的
mainDiffuseBRDF 亮度约束 Ramp 后的亮度,避免 Ramp 颜色把整体明度推得过高或压得过低。最后合并虚拟顶光和主光颜色:

4. 高光
高光部分使用 GGX 生成基础形状,再通过 Specular Ramp 做颜色重映射。
先从 MROMap 得到高光参数:
基础高光颜色根据 metallic 混合:
非金属区域通过 MROMap G 通道控制高光强度,金属区域更多继承 Albedo 颜色。
半角向量加入了相机前方向:
这个处理会让高光位置更偏角色展示。纯物理半角向量在镜头变化时容易让高光位置跳到不理想的位置,加入
cameraForward 后,高光会更稳定地服务于画面。GGX 计算:
Specular Ramp 采样:
默认模式下,Specular Ramp 主要受高光强度和粗糙度影响。
开启
_USE_IRIDESCENT_MODE 后,U 坐标改用 NoV * NoV,颜色会随视角变化,更适合虹彩、镀膜或特殊涂层。(这里只留了个开关,特殊材质还没做)最后高光乘上阴影相关权重,压制暗部高光:

5. 环境高光
首先是CubeMap
粗糙度越高,采样 mip 越高,反射越模糊。
然后计算近似环境 BRDF(数值拟合):
最终 Cubemap 贡献:
IBL 强度受到
virtualDiffInt 控制(这里其实应该是环境光的整体强度)。暗部仍然可以有反射,但整体强度会被压在可控范围内。

6. Rim
Rim 分成普通 Rim 和 BackLight Rim。
6.1 普通 Rim
普通 Rim 基于 Fresnel:
_RimArea 控制 Rim 范围。还要计算和相机相关的 Rim 方向:
再根据角色中心到当前像素的水平向量,控制 Rim 偏向合适的一侧:
最终普通 Rim:
_RimTint 控制 Rim 受 baseColor 染色的比例。
6.2 BackLight Rim
BackLight Rim 用来处理逆光边缘。
它主要综合这些因素:
- 当前镜头和主光是否接近背光关系。
- 表面是否处于视角边缘。
- 当前基础色是否偏暗。
- 法线和主光在水平面上的关系。
最终结果:

7. Emission
Emission 是最后的独立叠加项。

8. 合成
这里还有一段亮部去饱和处理:
它可以让高亮区域更干净,减少颜色过饱和。
最终合成大致是:
9. 最后
衣服部分还有一些特殊材质没有实现,最近去研究别的了,后续整理好了再发吧。


