您的位置:首页 > 移动开发 > Unity3D

游戏中实时皮肤渲染第二弹

2017-11-03 15:29 1366 查看
继上次渲染的皮肤之后,这次再写一篇可在游戏中应用的shader。

先上效果图(PS:游戏中的效果会比截图更好)。







这个shader主要用了以下几张贴图,皮肤贴图,法线贴图,AO贴图(g通道存储的在人脸越薄的地方值越大,例如耳朵,鼻子),曲率图。

shader面板如下:



接下来介绍主要部分代码:

光照衰减部分:

float attenuation = LIGHT_ATTENUATION(i);
float3 attenColor = attenuation * _LightColor0.xyz;


漫反射部分:

主要是曲率图的采样和环境光的一个相加值。

float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex));
float NdotL = max(0.0,dot( normalDirection, lightDirection ));
float3 directDiffuse = BentNormalsDiffuseLighting(normalDirection, lightDirection, Curvature, NdotL) ;
float3 indirectDiffuse = float3(0,0,0);
indirectDiffuse += UNITY_LIGHTMODEL_AMBIENT.rgb; // Ambient Light
float3 diffuseColor = (_Color.rgb*_MainTex_var.rgb);
float3 diffuse = (directDiffuse* attenColor + indirectDiffuse) * diffuseColor;
 曲率图的采样方法如下:
half3 BentNormalsDiffuseLighting(float3 normal, float3 L, float Curvature, float nl)
{
float NdotLBlurredUnclamped = dot(normal, L);
half3 diffuseLookUp = tex2Dlod(_LookUp, float4((NdotLBlurredUnclamped * 0.5 + 0.5), Curvature, 0, 0));

return diffuseLookUp;
}
  

曲率如何计算,我在之前已经介绍过了,曲率的计算

高光部分和常规一样:

float3 H = normalize(lightDirection + viewDirection);
float LdotH = saturate(dot(lightDirection, H));
float NdotH = saturate(dot(normalDirection, H));
float specularTerm = pow(NdotH, exp2(lerp(1, 11, _Smoothness)));


散射部分:

half3 transLightDir = lightDirection + normalDirection * _Lux_Skin_DeepSubsurface.y;
half transDot = dot(-transLightDir, viewDirection);
transDot = exp2((saturate(transDot)-1) * _Lux_Skin_DeepSubsurface.x) * _Translucency_var.g * _Lux_Skin_DeepSubsurface.z;
half3 lightScattering = transDot * _SubColor * attenColor;


其中_Lux_Skin_DeepSubsurface中的y存储的是一个对法线进行扭曲操作,x存储是对能量衰减的一个控制变量,z对效果的一个控制。

最后,计算AO

float3 finalColor = diffuse+ specularTerm*attenColor* FresnelTerm(_SpecColor, LdotH) + lightScattering;
finalColor *= _Translucency_var.a;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息