学习unity的surface shader中,先从角色的渲染搞起。
dota2的模型资源在
http://www.dota2.com/workshop/requirements 可以下载到
里面直接就有fbx的资源,还有材质的贴图。
直接导入unity工程就可以搞。dota2的模型有四张贴图,
先从简单的diffuse 贴图搞起,
直接上surface shader,和材质的结果:
Shader "Custom/actorDiffuse" { Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf BasicDiffuse #pragma target 2.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; float3 viewDir; }; inline float4 LightingBasicDiffuse(SurfaceOutput s, fixed3 lightDir, fixed atten) { float difLight = max(0, dot(s.Normal, lightDir)); float4 col; col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2); col.a = s.Alpha; return col; } void surf (Input IN, inout SurfaceOutput o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
其实关键的shader就几个地方,surf function中
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
对diffuse 贴图采样,
然后采用diffuse的光照计算模型
float difLight = max(0, dot(s.Normal, lightDir));
float4 col;
col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2);
这个atten 和 * 2,感觉是历史遗留问题。
然后是加入法线贴图:
Shader "Custom/actorDiffuseNormal" { Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} _NormalMap ("Normalmap", 2D) = "bump" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf BasicDiffuse #pragma target 2.0 sampler2D _MainTex; sampler2D _NormalMap; struct Input { float2 uv_MainTex; float2 uv_NormalTex; float3 viewDir; }; inline float4 LightingBasicDiffuse(SurfaceOutput s, fixed3 lightDir, fixed atten) { float difLight = max(0, dot(s.Normal, lightDir)); float4 col; col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2); col.a = s.Alpha; return col; } void surf (Input IN, inout SurfaceOutput o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = c.a; o.Normal = tex2D (_NormalMap, IN.uv_NormalTex); } ENDCG } FallBack "Diffuse" }
关键的一句就是
o.Normal = tex2D (_NormalMap, IN.uv_NormalTex);
就是法线的数据是直接从贴图上采样得到的
然后用mask2的贴图,做下specular,主要用了r和a两个通道
Shader "Custom/actorDiffuseMask" { Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} _NormalMap ("Normalmap", 2D) = "bump" {} _MaskMap ("Maskmap", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf BasicDiffuse #pragma target 2.0 sampler2D _MainTex; sampler2D _NormalMap; sampler2D _MaskMap; struct Input { float2 uv_MainTex; float2 uv_NormalTex; float2 uv_MaskTex; float3 viewDir; }; inline float4 LightingBasicDiffuse(SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten) { half3 h = normalize (lightDir + viewDir); float nh = max (0, dot (s.Normal, h)); float difLight = max(0, dot(s.Normal, lightDir)); float4 col; float spec = pow(nh, s.Specular); col.rgb = (s.Albedo * _LightColor0.rgb * difLight + _LightColor0.rgb * s.Gloss * spec ); col.a = s.Alpha; return col; } void surf (Input IN, inout SurfaceOutput o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = c.a; o.Normal = tex2D (_NormalMap, IN.uv_NormalTex); fixed4 mask = tex2D (_MaskMap, IN.uv_MaskTex); o.Specular = mask.a; o.Gloss = mask.r; } ENDCG } FallBack "Diffuse" }
就是这样了,之后有时间再搞其他的材质。