在一個基本模型裏,一個物體表面的顏色是由放射(emissive)、環境反射(ambient)、漫反射(diffuse)和鏡面反射(specular)等光照做用的總和。每種光照做用取決於表面材質的性質(如亮度和材質顏色)和光源的性質(如光的顏色和位置)的共同做用。html
從數學上描述基本模型的高級公式以下所示:ide
surfaceColor = emissive +ambient + diffuse + specularspa
1、放射項3d
emissive = Kecode
其中:orm
Ke表明材質的放射光顏色。htm
2、環境反射項blog
ambient = Ka * globalAmbientci
其中:get
Ka是材質的環境反射係數。
globalAmbient是入射環境光的顏色。
3、漫反射項
diffuse = Kd * lightColor * max(dot(N, L), 0)
其中:
Kd是材質的漫反射顏色。
lightColor是入射漫反射光的顏色。
N是規範化的表面法向量。
L是規範化的從頂點到光源的向量。
4、鏡面反射項
specular = Ks * lightColor * facing * pow(max(dot(N, H), 0), shininess)
其中:
Ks 是材質的鏡面反射顏色。
lightColor是入射鏡面反射光的顏色。
N是規範化的表面法向量。
H是規範化的,頂點到光源的向量與頂點到眼睛的向量的中間向量。
facing是,若是dot(N,L)大於0則爲1,不然爲0。其中L是頂點到光源位置的向量。
shinniess是表面光澤度。
例如,在unity3d shaderLab,在頂點shader中計算光照的代碼以下:
1 Shader "Custom/Test" 2 { 3 Properties 4 { 5 _Ke("Ke", Color) = (1,1,1,1) 6 _Ka("Ka", Color) = (1,1,1,1) 7 _GlobalAmbient("Global ambient", Color) = (1,1,1,1) 8 _Kd("Kd", Color) = (1,1,1,1) 9 _Ks("Ks", Color) = (1,1,1,1) 10 _Shininess("", float) = 1 11 } 12 13 SubShader 14 { 15 Pass 16 { 17 Tags 18 { 19 "RenderType" = "Opaque" 20 } 21 22 CGPROGRAM 23 #pragma vertex Vert 24 #pragma fragment Frag 25 26 #include "UnityCG.cginc" 27 #include "Lighting.cginc" 28 29 uniform float4 _Ke; 30 uniform float4 _Ka; 31 uniform float4 _GlobalAmbient; 32 uniform float4 _Kd; 33 uniform float4 _Ks; 34 uniform float _Shininess; 35 36 struct VertexInput 37 { 38 float4 pos : POSITION; 39 float2 uv : TEXCOORD0; 40 float3 nor : NORMAL; 41 float4 col : COLOR; 42 }; 43 44 struct FragmentInput 45 { 46 float4 pos : SV_POSITION; 47 float2 uv : TEXCOORD0; 48 float4 col : COLOR; 49 }; 50 51 FragmentInput Vert(VertexInput vi) 52 { 53 FragmentInput fi; 54 fi.pos = mul(UNITY_MATRIX_MVP, vi.pos); 55 fi.uv = vi.uv; 56 57 // compute emissive 58 float3 emissiveC = _Ke.rgb; 59 60 // compute ambient 61 float3 ambientC = _Ka.rgb * _GlobalAmbient.rgb; 62 63 // compute diffuse 64 float3 nor = mul(vi.nor, (float3x3)_World2Object); 65 float3 dir2Light = normalize(WorldSpaceLightDir(vi.pos)); 66 float nl = max(0, dot(nor, dir2Light)); 67 float3 diffuseC = _Kd.rgb * _LightColor0.rgb * nl; 68 69 // compute specular 70 float3 dir2Cam = normalize(WorldSpaceViewDir(vi.pos)); 71 float nh = max(0, dot(nor, dir2Cam + dir2Light)); 72 float specLight = nl > 0 ? pow(nh, _Shininess) : 0; 73 float3 specC = _Ks * _LightColor0.rgb * specLight; 74 75 fi.col.rgb = emissiveC + ambientC + diffuseC + specC; 76 fi.col.a = 1; 77 78 return fi; 79 } 80 81 float4 Frag(FragmentInput fi) : Color 82 { 83 return fi.col; 84 } 85 86 ENDCG 87 } 88 } 89 }
效果圖以下: