头发各向异性渲染Shader
这个是04年的一个ppt,主要介绍了头发的渲染,其追到源头还是要看这个原理。
各向异性的主要计算公式:
主要代码如下:
切线混合扰动部分(这部分也可以用T+k*N,来对切线进行扰动):
float3x3 tangentTransform = float3x3(i.tangentDir, i.bitangentDir, i.normalDir);
float3 _T_var = UnpackNormal(tex2D(_Tangent, TRANSFORM_TEX(i.uv0, _Tangent)));
float3 temp = lerp(_TangentParam.xyz, _T_var, _BlenfTangent);
float3 T = normalize(mul(float3(temp.xy,0), tangentTransform));
主要是通过改变切线的xy值来造成头发高光部分的多样性。
高光部分,按公式计算即可:
float StrandSpecular(float3 T, float3 V, float3 L, float exponent)
{
float3 H = normalize(L + V);
float dotTH = dot(T, H);
float sinTH = sqrt(1 - dotTH*dotTH);
float dirAtten = smoothstep(-1, 0, dotTH);
return dirAtten*pow(sinTH, exponent);
}
注意,为了模拟的更贴近真实性,应用两层高光,第一层高光代表直射光直接反射出去,第二层代表次表面散射现象具体看代码。
最终渲染部分:
float4 HairLighting(float3 T, float3 N, float3 L, float3 V, float2 uv, float3 lightColor)
{
float diffuse = saturate(lerp(0.25, 1.0, dot(N, L)))*lightColor;
float3 indirectDiffuse = float3(0, 0, 0);
indirectDiffuse += UNITY_LIGHTMODEL_AMBIENT.rgb; // Ambient Light
float3 H = normalize(L + V);
float LdotH = saturate(dot(L, H));
float3 specular = _Specular*StrandSpecular(T, V, L, exp2(lerp(1, 11, _Gloss)));
//float specMask = tex2D(_SpecMask, TRANSFORM_TEX(uv, _SpecMask));
specular += /*specMask*/_SubColor*StrandSpecular(T, V, L, exp2(lerp(1, 11, _ScatterFactor)));
float4 final;
float4 base = tex2D(_MainTex, TRANSFORM_TEX(uv, _MainTex));
float3 diffuseColor = (_Color.rgb*base.rgb);
//float ao = tex2D(_AO, TRANSFORM_TEX(uv, _AO)).g;
final.rgb = (diffuse + indirectDiffuse)*diffuseColor + specular*lightColor* FresnelTerm(_Specular, LdotH);
//final.rgb *= ao;
final.a = base.a;
clip(final.a - _CutOff);
return final;
}
这里我注释掉了AO和高光遮罩,需要的同学可以加上。
最后一点为了不让头发的边经过clip之后太硬,需要进行两个通道的belnd。
第二个pass使用以下指令:
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
注意第二个通道无需再进行clip操作。
至此,头发渲染完毕。
2021-12-11 23:02:48
253KB
头发渲染
1