DrawMeshInstanced 毛发渲染

一、效果展示

1.1 静帧效果

1.2 动态效果


二、技术拆解

2.1 整体架构与数据流向

  • 脚本组成
    • FurSkinBodyFurManagerFurDrawInstancedFeature(数据准备驱动与执行调度)
    • FurMaterialEyeMaterial(材质渲染效果)
  • 对应数据流向与处理
    • 单体 Mesh + VertexBuffer(Current + Previous)+ ShellCount (FurSkinBody)
    • VertexAllBuffer(CopyBuffer Compute Shader)+ InstanceDataBuffer + RigidVelocityBuffer + RigidOffsetBuffer (FurManager)
    • FurDrawInstancedFeature 执行 DrawMeshInstanced

2.2 FurShader 静态几何表现

  • 毛发基础形状:通过采样 Voronoi 贴图在 Fragment Shader 阶段进行 clip 操作;
  • 毛发长短:修改顶点色(Vertex Color)控制毛发长短:
  • 整体毛发卷曲度:通过重映射 remap(shellDepth, 1, -1) 模型世界空间法线的系数,配合后续 Flowmap + 毛发簇实现加强卷曲效果:
  • 低频毛发流向:自制毛发流向编辑器工具:
  • 中频毛发簇的实现
    • 形态参照
    • 通过 Substance Designer 获取 Voronoi 高度图 → 生成 flowmap_clump(向种子点内聚):
  • 几何效果迭代展示
    • 基础形状:
    • 叠加 Flowmap:
    • 叠加 Flowmap + Flowmap_clump:

2.3 着色模型

  • 毛发粗糙度渐变模型: 动物毛发通常内外毛粗糙度有明显变化,故根据 shellDepth 进行粗糙度的 Remap 映射。
  • 漫反射项
    • 直接光:半 Lambert(Half-Lambert)→ 模拟毛发多重散射导致的暗部偏亮提亮效果;
    • 间接光:基础漫反射环境光(Spherical Harmonics / Ambient)。
  • 镜面反射项
    • 直接光
      • Kajiya-Kay 模型:毛发的切线来源于几何部分的毛发形体(混合模型法线、Flowmap 与 Flowmap_clump);配合毛发粗糙度渐变模型,避免毛发显得油腻并具有丰富节奏变化: (具有渐变加强) (不具有渐变加强)
    • 间接光
      • 理想毛发法线:假设光线只打入毛发圆柱体过中轴线的一点,推导公式: 根据理想毛发法线进行镜面反射环境光(IBL Specular)计算。
    • SSS(次表面散射): 通过 LightDir、-ViewDir 与模型世界空间法线进行混合与加权计算:

2.4 骨骼层级毛发摆动效果(物理模拟)

来源于 RigidOffsetBuffer,根据胡克定律(弹簧-阻尼系统)进行物理模拟:

2.5 EyeShader(眼球渲染)

  • 视差映射(角膜折射模拟): 通过模型空间 Y 值与 Height Property 差值确定虹膜深度,根据深度与 ViewDirOS 进行 UV 偏移: (视差映射 Off) (视差映射 On)
  • 虹膜漫反射 + 风格化角膜焦散
    • 法线变换(模拟虹膜内凹结构)
      float3 N_iris = reflect(-N, TransformObjectToWorldDir(float3(0, 1, 0)));
    • 焦散表现:在虹膜漫反射基础上做范围 Power 增强 + 焦散 Mask:
  • 整体非线性混合: 眼白镜面反射 + 角膜镜面反射 + 虹膜漫反射 + 风格化角膜焦散,使用 Sigmoid 函数对模型空间 Y 值与 Height Property 差值做 Remap(): (非线性混合 On) (非线性混合 Off)

三、骨骼层级毛发摆动效果的具体实现

  • 数据流向SkinMeshRenderer.VertexBuffer + SkinMeshRenderer.PreviousVertexBufferRigidOffsetBuffer + RigidVelocityBufferFurShader 毛发偏移采样
  • Offset + Velocity 的计算原理(胡克定律 弹簧-阻尼模型)
    • 毛发外力来源(以骨骼坐标系为参考系)
      • 阻尼项:空气阻力与其他损耗(数值与速度大小呈正相关);
      • 弹簧力项:
    • 公式递推

四、渲染性能优化

  • 毛发几何生成技术支持
    • DrawMeshInstanced:相对于传统多 Pass 绘制,已将 DrawCall 降低为 1 次;
    • Clip 指令缺陷:若 ZWrite On,GPU 的 Early-Z 硬件深度剔除失效,导致大量被遮挡毛发产生冗余片元计算。
  • 解决 Clip 导致的冗余片元计算方案
    • DepthOnlyPass (PreDepth):共用正常 Pass 的顶点着色器,Fragment 阶段仅做 clip 判断,不进行复杂光照着色;
    • NormalPass / ForwardPass:开启 ZWrite Off,重新激活 Early-Z 剔除。
  • 优化前后帧时间对比 (优化前: 1.36ms) (优化后: 1.08ms) 在近距离特写视角下,片元计算压力极大,该项优化带来的性能提升尤为显著。

五、美术与审美拆解

  • 原始模型贴图来源于网络资源;
  • 毛发形态的节奏差异
    • 基础 Shell 毛发(高频细节);
    • 毛发簇实现(中频结构);
    • 毛发整体流向(低频大势)。
  • 眼球虹膜贴图设计(色彩对比)
    • 虹膜最外层选取模型身体贴图颜色的低饱和互补色(兼顾整体和谐与细节差异);
    • 虹膜内层设计互补色渐变过渡(在差异化前提下保持视觉舒适);
    • 虹膜纹理节奏严格控制在中频与相对低频之间。

六、个人进一步思考与架构演进

  • 架构演进:当前架构对场景内单体具有毛发的角色属于最优解;但对于群体同屏角色,架构仍需升级:
    • 动画去重(VertexBuffer 去重) → 极大降低 VRAM 显存占用;
    • 逐去重 Mesh + One Material + MaterialDataBuffer 执行 DrawInstance → 使总 DrawCall 数量仅与 Mesh 种类数正相关;
    • 针对当前 Single VertexBuffer -> VertexAllBuffer 架构中存在的 VRAM 内存拷贝消耗,探索更直接的 Buffer 映射优化。