终末地 - 角色渲染
一、美术分析
整体风格 :具有工业机能风质感的二次元 NPR(脸部与发丝高度风格化,身体服饰与金属部件引入微表面 PBR)。
色彩与明暗表现 :
主光分界清晰,通过可调 Ramp 控制阴影软硬与过渡阶梯;
阴影区带有明显的明度保底与饱和度补偿(SatColor),避免二次元暗部发灰发脏;
边缘光硬朗且与主光及相机朝向产生联动,暗面不漏光。
二、技术实现
1. 自阴影方案(Per-Object Shadow)
问题 :URP 自带的 CSM 级联阴影在角色特写视角下分辨率不足,自阴影走样锯齿严重且容易产生 Shadow Acne 穿帮。
实现方案 :
RendererFeature 驱动 :PerObjectShadowFeature 抓取角色整体蒙皮包围盒(SkinnedMesh Bounds),根据主光方向构建紧贴角色的专用正交投影矩阵,绘制 2048×2048 独立深度图(_PerObjShadowMap);
4-Tap 硬件 PCF 滤波 :片元阶段通过 4 次硬件比较采样配合双线性权重重构覆盖 3×3 范围,以极低开销换取平滑柔和的自阴影边缘。
2. 通用身体与服饰
1. RMA 贴图通道规范 :
R: Metallic(金属度)
G: Specular(高光强度)
B: AO(环境光遮蔽)
A: Smoothness(光滑度)
2. 直接光漫反射(Keylight 调制的 Diffuse Ramp) :
虚拟导向光偏移:主光 L 与可配偏移矢量 _KeyLOffset 插值得到 KeyL;
在 XZ 平面上计算 L 与 K ey L 夹角得出背光强度 KeyStrength,结合太阳高度天顶角衰减生成门控信号 keyToggle;
采样坐标解算:
r am p U = clamp ( r a w N d o t L + k ey T o g g l e ⋅ ( 1 − r a w N d o t L 2 ) ⋅ 0.5 + B ia s , − 1 , 1 ) ⋅ 0.5 + 0.5
分阶过渡与暗部保底:暗部采用 diffuseColor * 0.65 保底,中间调 diffuseColor * 0.85 与 Ramp 采样值插值,提取 Ramp 高饱和度成分补偿色彩,防止阴影脏灰。
3. 直接光镜面反射 :
基于微表面 Cook-Torrance BRDF(D-GGX + Smith-Vn + Schlick-F),非金属使用 Specular 决定 F 0 ,金属使用 BaseColor,镜面项受 shadow * ao 严格衰减。
4. 边缘光(Cross-Axis Rim Light) :
相机空间世界轴与主光做叉乘生成虚拟边缘光轴 rimLightAxisDir;
边缘光由该轴向投影与菲涅尔项联合驱动,并受自阴影、AO 与光滑度衰减,暗面不漏光。
3. 面部与皮肤
1. Light SDF 面部阴影 :
提取头部模型空间的 Right、Up、Forward 局部基底向量转到世界空间;
主光方向与 Right 轴点积判断光源左右,实时水平翻转 _LightSDF 采样 UV(uvSDF.x = 1.0 - uvSDF.x),实现单贴图左右对称复用;
阈值映射:t h r es h o l d = 1.0 − L i g h tS D F ,通过 smoothstep 将前向投影点积转化为纯净无杂光的二次元脸部明暗交界线。
2. 面颈解耦与阴影防漏 :
MaskTex.g 区分脸部与脖子/耳朵:脸部走 SDF 计算且完全屏蔽外部硬自阴影(shadowAtten = lerp(1.0, shadow, mask.g)),脖子则保留正常法线光照与自阴影。
3. 挺鼻动态微阴影 :
利用 BaseMap 的 Alpha 通道遮罩配合侧光分量 abs(dotRightL) 动态压暗鼻子侧翼,一行代码还原二次元侧光时精致的小挺鼻投影。
4. 皮肤高光与边缘光 :
独立 _SpecularMask 控制面部与唇部局部高光,MaskTex.a 限制皮肤边缘光范围。
4. 头发渲染
1. 法线解耦 :
NormalMap 的 RG 通道解算漫反射法线(驱动 Ramp 漫反射与边缘光);BA 通道独立用于高光切线解算。
2. 球形切线与顶点切线混合 :
片元阶段用模型空间竖直轴(由模型 X 轴与 Z 轴叉乘求得)与高光法线叉乘生成经纬向“球形切线”(t_Spherical);
_RMATex.r 作为遮罩切换:大片主发体采用球形切线统一光泽形态,细碎小发片切回顶点切线,消除二次元发片模型接缝处的切线断层。
3. Kajiya-Kay + 2D Specular LUT(天使环高光) :
切线扰动:采样 _TangentOffsetMap 并结合常数 _TangentShift,使切线沿法线偏移产生锯齿抖动和双层高光;
正弦各向异性项:sin ( T , H ) = 1 − ( T ⋅ H ) 2 ;
视线与法线截面点积计算纵向衰减 lutV,组成二维 UV 采样 _HairSpecularLUT,实现高光形态分阶、边缘羽化的日系天使环。
4. 双 Pass 与深度层级 :
ForwardLit(AlphaTest 剪裁主发体)+ TransHair(半透明混合发梢边缘);
结合 Stencil 模板测试,实现二次元标志性的“透发见眉/透发见眼”层级。
5. 眼球渲染
1. 程序化半球法线(零贴图消耗) :
直接将 UV 映射至 [ − 1 , 1 ] 范围,根据球面方程计算凸半球法线:
float2 uvOffset = (input.uv - 0.5 ) * 2.0 ;
float x = uvOffset.x * _MatCapNormalStrength;
float y = uvOffset.y * _MatCapNormalStrength;
float z = sqrt ( saturate ( 1.0 - x * x - y * y));
float3 normalTS = float3 (x, y, z);
2. 晶状体折射视差(Cornea Parallax Mapping) :
视线投影到切线空间后根据半球深度 z 对 UV 进行视差反向推移:
parallaxUV = input.uv - viewDirTS.xy * (z * _ParallaxStrength)
模拟透明角膜与深陷眼底虹膜的物理立体视差。
3. 凹面虹膜反向受光(Inner Eye Specular) :
构造反向内凹法线 N inn er = ( − x , − y , z ) ,采样 1D Ramp 贴图(_InnerEyeMap),生成跟随光源移动的下半弧内聚反光。
4. 视口空间 MatCap :
凸半球代理法线变换到 View Space(V S x y × 0.5 + 0.5 )采样 MatCap,模拟角膜表面犹如摄影棚反光板的晶莹质感。
6. 描边(Outline)
1. 八面体平滑法线解包(OctahedralNormal.hlsl) :
DCC 软件中预计算平滑法线,利用八面体投影压缩至 2D 坐标存储于 TEXCOORD1;
顶点着色器解码后沿平滑法线外扩顶点,彻底解决硬表面折角和发梢尖锐处的描边撕裂断线问题。
2. 动态受光着色 :
描边片元并非纯黑,而是复用主光 Diffuse Ramp 与 Rim Light 进行动态染色,并提供饱和度控制调节,使轮廓线自然融入环境氛围。
8. 特殊材质
1. 镭射薄膜(Laser Iridescence) :
视线角平方 ( N ⋅ V ) 2 采样光谱渐变 Ramp(_SpecRampMap),直接加成至镜面反射项,模拟科技机能透明雨衣/斗篷的彩虹偏光质感。
2. 丝袜材质(Silk Stocking) :
结合 BaseMap 的 Alpha 遮罩与菲涅尔非线性调制,实现垂直视角透出肤色、边缘掠射角呈现织物密织漫反射与边缘光。