游戏中各向异性头发的渲染

来源:互联网 发布:虾囧cms 编辑:程序博客网 时间:2024/04/27 21:58

趁有时间写一篇关于各向异性头发的渲染。

先上效果图(不含Ao)。






这个是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 Lightfloat3 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操作。


至此,头发渲染完毕。