终末地 - 角色渲染

一、美术分析

  • 整体风格:具有工业机能风质感的二次元 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)
    • 虚拟导向光偏移:主光 与可配偏移矢量 _KeyLOffset 插值得到 KeyL
    • 在 XZ 平面上计算 夹角得出背光强度 KeyStrength,结合太阳高度天顶角衰减生成门控信号 keyToggle
    • 采样坐标解算:
    • 分阶过渡与暗部保底:暗部采用 diffuseColor * 0.65 保底,中间调 diffuseColor * 0.85 与 Ramp 采样值插值,提取 Ramp 高饱和度成分补偿色彩,防止阴影脏灰。
  • 3. 直接光镜面反射
    • 基于微表面 Cook-Torrance BRDF(D-GGX + Smith-Vn + Schlick-F),非金属使用 Specular 决定 ,金属使用 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),实现单贴图左右对称复用;
    • 阈值映射:,通过 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,使切线沿法线偏移产生锯齿抖动和双层高光;
    • 正弦各向异性项:
    • 视线与法线截面点积计算纵向衰减 lutV,组成二维 UV 采样 _HairSpecularLUT,实现高光形态分阶、边缘羽化的日系天使环。
  • 4. 双 Pass 与深度层级
    • ForwardLit(AlphaTest 剪裁主发体)+ TransHair(半透明混合发梢边缘);
    • 结合 Stencil 模板测试,实现二次元标志性的“透发见眉/透发见眼”层级。

5. 眼球渲染

  • 1. 程序化半球法线(零贴图消耗)
    • 直接将 UV 映射至 范围,根据球面方程计算凸半球法线:
      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)
    • 视线投影到切线空间后根据半球深度 对 UV 进行视差反向推移: parallaxUV = input.uv - viewDirTS.xy * (z * _ParallaxStrength) 模拟透明角膜与深陷眼底虹膜的物理立体视差。
  • 3. 凹面虹膜反向受光(Inner Eye Specular)
    • 构造反向内凹法线 ,采样 1D Ramp 贴图(_InnerEyeMap),生成跟随光源移动的下半弧内聚反光。
  • 4. 视口空间 MatCap
    • 凸半球代理法线变换到 View Space()采样 MatCap,模拟角膜表面犹如摄影棚反光板的晶莹质感。

6. 描边(Outline)

  • 1. 八面体平滑法线解包(OctahedralNormal.hlsl
    • DCC 软件中预计算平滑法线,利用八面体投影压缩至 2D 坐标存储于 TEXCOORD1
    • 顶点着色器解码后沿平滑法线外扩顶点,彻底解决硬表面折角和发梢尖锐处的描边撕裂断线问题。
  • 2. 动态受光着色
    • 描边片元并非纯黑,而是复用主光 Diffuse Ramp 与 Rim Light 进行动态染色,并提供饱和度控制调节,使轮廓线自然融入环境氛围。

8. 特殊材质

  • 1. 镭射薄膜(Laser Iridescence)
    • 视线角平方 采样光谱渐变 Ramp(_SpecRampMap),直接加成至镜面反射项,模拟科技机能透明雨衣/斗篷的彩虹偏光质感。
  • 2. 丝袜材质(Silk Stocking)
    • 结合 BaseMap 的 Alpha 遮罩与菲涅尔非线性调制,实现垂直视角透出肤色、边缘掠射角呈现织物密织漫反射与边缘光。