【猫猫的Unity Shader之旅】之高光材质

  之前我们的Shader用的光照模型都是Lambert,这种光照表示的是一种漫反射的情况。所谓的漫反射,表示的是光线照射在粗糙的表面的情况。由于表面粗糙,根据反射的规律,光线会被反射到各个方向。现实生活中有许多漫反射的情况,木头桌子,岩石,墙面,都是漫反射。

  但是只有漫反射是不够的,现实中还有许多其他的情况。其中一种就是我们今天讨论的高光情况,高光其实表示的是一种接近于镜面反射的效果。对于镜面反射,由于反射的方向比较固定,导致我们可以再某个点看到大部分的反射光,而在其他店看不到或者只能看到很少的光。也就是说,当有反射光线进入眼睛我们会在材质上看到一个很亮的部分,反之则会很暗。常见的高光效果有汽车表面的金属材质,油漆过的家具表面,还有猫猫三天没有洗的头发~~~

高光材质的光照模型分析

  显然,Lambert光照模型并不能实现高光效果,我们需要用到新的光照模型:Phong和BlinnPhong。

  这些光照模型,之前也有说过,其实是一种算法,根据SurfaceOutput中的信息,最终计算出片段颜色。但是要问为什么要这么算,就有点复杂了,因为Shader的算法有很多时候不像平时程序的算法,有个总体的思路。像光照模型之类的算法的产生,,基本上有两种:模拟自然界的物理规律,利用复杂的计算产生真实的效果和利用经验调出以假乱真的效果。不论是哪种形式,都不是适合初学者去学习和掌握的,所以猫猫觉得,我们学习某种光照模型,对于它为何要这样计算,现阶段更多的是有个了解,最重要的是,去学习如何使用它以及用到的一些知识和技术。

  对于BlinnPhong光照,Lighting.cginc里面为我们提供了实现,我们可以用#pragma surface surf BlinnPhong来使用它。现在,我们可以先简单的了解下这个模型:

inline fixed4 LightingBlinnPhong (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten){half3 h = normalize (lightDir + viewDir);fixed diff = max (0, dot (s.Normal, lightDir));float nh = max (0, dot (s.Normal, h));float spec = pow (nh, s.Specular*128.0) * s.Gloss;fixed4 c;c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2);c.a = s.Alpha + _LightColor0.a * _SpecColor.a * spec * atten;return c;}

  虽然不懂BlinnPhong为何要这么计算,但是我们可以发现它用到了三个变量_SpecColor、s.Specular和s.Gloss。_SpecColor直接参与了最终颜色值得计算,_LightColor0.rgb * _SpecColor.rgb * spec这部分对原有光照的颜色进行了补充,其实就是高光部分的颜色,而s.Specular和s.Gloss参与了spec的计算,控制了高光的范围和强度。

  下面让我们来用一用这个光照模型吧:

Shader “Custom/HighLight” {Properties {_MainTex (“Base (RGB)”, 2D) = “white” {}_SpecColor(“Specular Color”, Color) = (1, 1, 1, 1)_SpecularPower(“Specular Power”, Range(0.01, 1)) = 1_Gloss(“Gloss”, Range(0.01, 10)) = 0.5}SubShader {Tags { “RenderType”=”Opaque” }LOD 200CGPROGRAM#pragma surface surf BlinnPhongsampler2D _MainTex;float _SpecularPower;float _Gloss;struct Input {float2 uv_MainTex;};void surf (Input IN, inout SurfaceOutput o) {half4 c = tex2D (_MainTex, IN.uv_MainTex);o.Specular = _SpecularPower;o.Gloss = _Gloss;o.Albedo = c.rgb;o.Alpha = c.a;}ENDCG}FallBack “Diffuse”}

  运行效果如图:

  

利用贴图模拟不同部分的高光

  上面的效果符合单一材质的高光效果,比如汽车车身的亮斑,但是如果要表现复杂的情况,比如一些锈迹斑斑的金属,没有生锈的地方我们希望它有强烈的高光,生锈的地方希望没有或者只有少量的高光。这就需要我们对模型不同部位的高光强度区别对待了,而最擅长做这种区别处理的,显然就是贴图了。明白了这个道理,代码其实就很简单了:

Shader “Custom/HighLight” {Properties {_MainTex (“Base (RGB)”, 2D) = “white” {}_SpecColor(“Specular Color”, Color) = (1, 1, 1, 1)_SpecularMap(“Specular Map”, 2D) = “white”{}_Gloss(“Gloss”, Range(0.01, 10)) = 0.5}SubShader {Tags { “RenderType”=”Opaque” }LOD 200CGPROGRAM#pragma surface surf BlinnPhongsampler2D _MainTex;sampler2D _SpecularMap;float _SpecularPower;float _Gloss;struct Input {float2 uv_MainTex;};void surf (Input IN, inout SurfaceOutput o) {half4 c = tex2D (_MainTex, IN.uv_MainTex);half4 s = tex2D (_SpecularMap, IN.uv_MainTex);o.Specular = s.r;o.Gloss = _Gloss;o.Albedo = c.rgb;o.Alpha = c.a;}ENDCG}FallBack “Diffuse”}结束语

  这段时间工作一直比较忙,更新的比较慢了,这篇文章写得也是比较匆忙。关于高光这部分,主要是学会如何去使用,顺便大概地了解下工作原理。再见~

我只愿,在你的理想和希望里能为你增加一点鼓励,

【猫猫的Unity Shader之旅】之高光材质

相关文章:

你感兴趣的文章:

标签云: