您的位置:首页 > 其它

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

2017-11-03 16:29 561 查看
趁有时间写一篇关于各向异性头发的渲染。

先上效果图(不含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 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操作。

至此,头发渲染完毕。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息