Shader - Hair & Fur

 Demo



Mesh

无论是头发材质还是毛发材质,它们的建模都是基于插片的方式,且每个片都是单面(Cull Off)

UV Layout

需要保证Kajiya-Kay高光流向的连续性,UV的布局要是统一且具有方向性的,每个网格片的UV区域重复覆盖。

Vertex Occlusion

通过烘焙保存在顶点颜色的环境光遮蔽,不同于使用AO贴图的方式。离线的烘焙可以计算出不同层级(插片)互相之间的遮挡关系。区别不同层级受到的环境光遮蔽,提升整个毛发渲染的阴影体积感。

Pass

渲染效果分为两个品质:
  • Alpha Test(适用中低性能的设备)
  • Alpha Test + Alpha Blend(适用高性能的设备)
两个Pass使用的都是同一张Alpha贴图。


Alpha Test

只有一个裁剪Pass,所有毛发的边缘都会被硬切,整个毛发的渲染效果就显得比较毛糙,完全没有柔软感。但是性能方面相对的比较好,写入了深度值,不会导致严重的Overdraw。

Alpha Blend

再加上一个混合Pass,每一根毛发的边缘都变成半透明状态,锯齿感会明显减少,整个毛发的渲染效果也会显得比较有柔软感。但是裁剪(Alpha Test)Pass必须作为基础,因为混合Pass要依赖它提前的深度写入来进行深度测试,从而避免出现错误的混合层级和顺序,还能减少大部分区域的Overdraw。另外一个需要注意的是,因为深度值精度的有限,同一个三角面的混合Pass和裁剪Pass可能会发生深度冲突。为了有正确的渲染效果,要让混合Pass始终能覆盖在裁剪Pass上。使用Shader提供的Offset设置渲染状态,能对混合Pass的深度值进行非常轻微的偏移,这样在不影响渲染效果(透视)的前提下避免了深度冲突。
混合Pass渲染状态:
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
Offset 1, -1

Specular

高光是各向异性的,它的流向是依据毛发的方向(顶点空间的切线或次切线)
镜面高光的D项是Kajiya-Kay,F项是Schlick,V项用常量0.25代替。

Kajiya-Kay

// Note: Kajiya-Kay is not energy conserving.
// We attempt at least some energy conservation by approximately normalizing Blinn-Phong NDF.
// We use the formulation with the NdotL.
// Note: this is Blinn-Phong, the original paper uses Phong.
real3 D_KajiyaKay(real3 T, real3 H, real specularExponent)
{
    real TdotH = dot(T, H);
    real sinTHSq = saturate(1.0 - TdotH * TdotH);

    real dirAttn = saturate(TdotH + 1.0);

    real n = specularExponent;
    real norm = (n + 2) * rcp(2 * PI);

    return dirAttn * norm * PositivePow(sinTHSq, 0.5 * n);
}

Dual Lobe

同时使用两个高光瓣,是为了模拟毛发的散射特性。通过Shift顶点空间的切线或次切线,可以分别偏移两个高光的流向,互相之间形成错位分布。
real3 ShiftTangent(real3 T, real3 N, real shift)
{
    return normalize(T + N * shift);
}
主高光是镜面反射造成的,高亮且没有色彩;次高光是散射特性造成的,相对较弱并带有色彩。

Flow Map

在某些特殊的用法或建模情况下,UV布局不能保证是连续的,顶点空间的切线不是连续的。这就会导致高光的流向也不能保持连续性,出现了断裂的情况。


使用Flow Map技术可以重新定义高光的流向,不再完全依赖顶点空间的切线方向。它的原理是通过使用贴图的两个通道,分别对切线方向和次切线方向产生偏移,最后计算出单位矢量和作为高光的流向。其中需要特别注意的是,LDR贴图的值范围是0 ~ 1,要把范围映射到-1 ~ 1后才能表达矢量方向的正反。
(1 - 2 * map.x) * tangent + (1 - 2 * map.y) * bitangent

评论

此博客中的热门博文

Shader - Skin & SSS

一个Mesh的半透明类型