赞
踩
人生的前言:
许久未更新技术博客,这次也是很荣幸能够借助sorumi大佬的教程,重新捡起shader。
suorumi大佬的文章链接如下。
https://sorumi.xyz/posts/unity-fur-shader/
毛发材质的模型:
大家都知道传统光照模型下,单次渲染流程,难以满足很多特别材质的视觉效果要求。像毛发材质就是其中的一种,即便是有了纹理贴图的加成,那个僵硬的边缘都在表示这个东西跟软乎乎的绒毛不是一个东西。
实际上,绒毛材质的物理表现往往由多个层次组合体现。总结来说就是:逐层分布,越往上越稀疏。
毛发材质的渲染
根据这个特点,我们通过设置多个pass的方式,每一个pass绘制一层,从而实现出体积感的效果。具体而言,就是沿着物体的法线,逐步绘制每一层。在顶点着色器中让顶点坐标沿着法线方向,随着步数逐步外推,片元着色器中随着步数逐渐降低透明度。
顶点着色器计算顶点偏移的部分
_FurLength 毛绒长度参数,FURSTEP 表示当前层数 / 总层数,增加层数可以创造更精细毛发。
float3 P = v.vertex.xyz + v.normal * _FurLength * FURSTEP;
o.pos = UnityObjectToClipPos(float4(P, 1.0));
片元着色器的透明度计算部分
这里我也没太推明白为什么是 FURSTEP乘FURSTEP,_FurDensity值的设置主要影响绒毛的密度,_FurDensity值越大,绒毛材质显得更紧凑,反之显得更蓬松。
fixed alpha = clamp(noise - (FURSTEP * FURSTEP) * _FurDensity, 0, 1);
相对大的_FurDensity值的效果
相对小的_FurDensity值的效果,材质显得更软乎
在最终的渲染流程中,通过定义不同的FURSTEP实现多个pass渲染。
其他参数
毛发细密度,主要调整绒毛的平铺程度,共同作用于最后的透明度计算,能够获取看起来更细致的绒毛效果。
fixed3 noise = tex2D(_FurTex, i.uv.zw * _FurThinness).rgb;
fixed alpha = clamp(noise - FURSTEP * FURSTEP * FURSTEP * _FurDensity, 0, 1);
_FurThinnesss值偏小的效果
_FurThinnesss值偏大的效果
毛发根部阴影,越靠近根部,由于遮挡效果,阴影越深。
fixed3 albedo = tex2D(_MainTex, i.uv.xy).rgb * _Color;
albedo -= (pow(1 - FURSTEP, 3)) * _FurShading;
个人觉得_FurShading是这个shader里面比较有意思的参数,虽然数值上只能设置在一个较小的值范围内,不然很容易出现荨麻疹一样的效果(密恐人直呼害怕),也不知道是不是我这个贴图的问题。这里我录了一个gif来说明效果,gif展现了_FurShading值由小到大再到小的效果。
剩下的部分就是外力和边缘光,这两点在原文章里也有提及,这里就不附图展开了。
外力主要作用于顶点着色器,使顶点沿设定的方向发生偏移,模拟重力或者风力对绒毛影响的效果。
float3 P = v.vertex.xyz + v.normal * _FurLength * FURSTEP;
P += clamp(mul(unity_WorldToObject, _ForceGlobal).xyz + _ForceLocal.xyz, -1, 1) * pow(FURSTEP, 3) * _FurLength;
边缘光就是经典模型,共同作用于片元着色器的albedo。
half rim = 1.0 - saturate(dot(worldView, worldNormal));
albedo += fixed4(_RimColor.rgb * pow(rim, _RimPower), 1.0);
与经典光照模型的对比效果如下,可以看到多pass营造的体积感还是比较好的。
工程源码请参考附的链接。
绒毛贴图:
没有查证是否为公开版权图片,请勿用于学习以外用途。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。