金屬效果html
該光照模型是基於物理材質的光照模型。光照射到物體表面發生漫反射、鏡面反射、折射、透射等現象,在這裏咱們只考慮漫反射和鏡面反射,Cook-Torrance是用來模擬不一樣材質的鏡面反射效果。app
其中:函數
ambient :環境光;spa
K:決定高光部分和漫射的比例,通常而已,光復合能量守恆定律,即入射光的總能量和出射光的總能量相等;code
rs :鏡面發射;orm
即Fresnel,菲涅爾反射。咱們在觀察水面的時候,垂直看下去,清澈見底,看遠處的水面,向鏡子同樣,這個就是菲涅爾效應。菲涅爾效應能夠說是無處不在,不一樣的材質效果不一樣而已。htm
v:視點的方向;blog
h:半角向量,即視點和光線的中間向量;get
該項模擬物體表面是由無數微小的像鏡子同樣的平面組成,每個微平面對於光線會根據自身的方向反射光線,只有那些面向視點的平面貢獻大。具體參見微平面法線分佈的理論。it
該項用於計算微平面中反射光重合部分的修正。
=============================================================================
Shader "JQM/Cook-Torrance" { Properties { _Color("Base Color",Color) = (1,1,1,1) _MainTex ("Texture", 2D) = "white" {} _Roughness("Roughness",Range(0,1)) = 1 _Fresnel("Fresnel",Range(0,1)) = 1 _K("K",Range(0,1)) = 1 _Environment ("Environment", Cube) = "white" } SubShader { Pass { Tags { "LightMode" = "ForwardBase"} CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" float4 _Color; //使用Unity定義的變量:燈光 uniform float4 _LightColor0; float _Roughness; float _Fresnel; float _K; samplerCUBE _Environment; struct VertexOutput { float4 pos : SV_POSITION; float4 posWorld : TEXCOORD1; float2 uv : TEXCOORD2; float3 normal:Normal; }; sampler2D _MainTex; float4 _MainTex_ST; VertexOutput vert (appdata_full v) { VertexOutput o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.posWorld = mul(_Object2World, v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.normal = v.normal; return o; } fixed4 frag (VertexOutput i) : COLOR { //將法線轉到世界空間:乘以變換矩陣的逆的轉置 //float3 normalWorld = mul(_Object2World,i.normal); float3 normalWorld = mul(i.normal,_World2Object); //觀察者 float3 eyeDir = normalize(_WorldSpaceCameraPos -i.posWorld).xyz; //光源 float3 lightDir = normalize(_WorldSpaceLightPos0).xyz; fixed4 col = tex2D(_MainTex, i.uv); ///計算漫反射 float3 diffuse = _Color; //計算天空盒 float3 r = reflect(-eyeDir,normalWorld); float4 reflectiveColor = texCUBE(_Environment,r); //計算高光 //float3 h = (eyeDir+lightDir)/2; //float3 r = normalize(reflect(-lightDir,normalWorld)); //float3 specular = saturate(dot(lightDir,normalWorld))* _SpecularColor * pow(saturate(dot(r,eyeDir)),_SpecularPower); //計算Cook-Torrance高光 float s; float ln = saturate(dot(lightDir,normalWorld)); if(ln > 0.0)//在光照範圍內 { float3 h = normalize(eyeDir+lightDir); float nh = saturate(dot(normalWorld, h)); float nv = saturate(dot(normalWorld, eyeDir)); float vh = saturate(dot(eyeDir, h)); //G項 float nh2 = 2.0*nh; float g1 = (nh2*nv)/vh; float g2 = (nh2*ln)/vh; float g = min(1.0,min(g1,g2)); //D項:beckmann distribution function float m2 = _Roughness*_Roughness; float r1 = 1.0/(4.0 * m2 *pow(nh,4.0)); float r2 = (nh*nh -1.0)/(m2 * nh*nh); float roughness = r1*exp(r2); //F項 float fresnel = pow(1.0 - vh,5.0); fresnel *= (1.0-_Fresnel); fresnel += _Fresnel; s = saturate((fresnel*g*roughness)/(nv*ln*3.14)); //reflectiveColor *= fresnel; } float3 final =_LightColor0*ln*(_K*diffuse*reflectiveColor*2 + s*(1-_K)*reflectiveColor*2) + UNITY_LIGHTMODEL_AMBIENT.xyz; return float4(final,1); } ENDCG } } }
參考資料: