【舊博客轉移 - 2016年4月3日 23:27】
前面的話:
在現實生活中,我們看見能看見的東西都是光反射出來的顏色,如果反射光太弱,或者沒有進入你的視角范圍,你看到的就是黑色的。
在游戲中光分為幾種,平行光源(太陽光),點光源(燈泡)等等,最常用的是Directional light(平行光源)。
當然在計算機中光不過是一些數據罷了,
方向,顏色,亮度就可以決定一個平行光源
漫反射光照:
漫反射是是投射在粗糙表面上的光向各個方向反射的現象,根據入射光線與此點的法線來決定此點的反射強度,
用ShaderLab書上的公式表達就是
Lum = C * max(0, cos<L, N>)
C:到達此點光線的強度和顏色
N:法線
L:單位長度(標准化)的入射光向量
Shader "lijia/Diffcue" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float3 normal : TEXCOORD1; float3 lightDir : TEXCOORD2; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _LightColor0; v2f vert (appdata_full v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.normal = v.normal; o.lightDir = ObjSpaceLightDir(v.vertex);//把光向量從世界空間轉成模型空間 return o; } fixed4 frag (v2f i) : SV_Target { float3 L = normalize(i.lightDir); float3 N = normalize(i.normal); fixed4 col = tex2D(_MainTex, i.uv); float diff = max(0, dot(N, L)) * _LightColor0.rgb + UNITY_LIGHTMODEL_AMBIENT;//加上環境光 return col*diff; } ENDCG } } }
這里要注意的是,計算LightDir跟Normal的夾角的時候,一定要保證在同一個坐標空間。有兩種方式
- 把LightDir轉成模型空間
- 把Normal轉世界空間
但是把Normal轉世界坐標一定要注意,不要用mul(_Object2World, normal)去轉,這樣如果模型有一些縮放變化就會出現異常。正確的做法是用模型到世界的逆矩陣的轉置矩陣。mul(float4(normal, 0), _World2Object);
漫反射效果:
適合用在地形,岩石,牆壁等粗糙的物體上,人物可以使用更炫麗的光照計算,比如下一篇要寫的 鏡面高光和Phong