CG之基本光照模型计算公式

在一个基本模型里,一个物体表面的颜色是由放射(emissive)、环境反射(ambient)、漫反射(diffuse)和镜面反射(specular)等光照作用的总和。每种光照作用取决于表面材质的性质(如亮度和材质颜色)和光源的性质(如光的颜色和位置)的共同作用。

从数学上描述基本模型的高级公式如下所示:

surfaceColor = emissive +ambient + diffuse + specular

 

一、放射项

emissive = Ke

其中:

Ke代表材质的放射光颜色。

 

二、环境反射项

ambient = Ka * globalAmbient

其中:

Ka是材质的环境反射系数。

globalAmbient是入射环境光的颜色。

 

三、漫反射项

diffuse = Kd * lightColor * max(dot(N, L), 0)

其中:

Kd是材质的漫反射颜色。

lightColor是入射漫反射光的颜色。

N是规范化的表面法向量。

L是规范化的从顶点到光源的向量。

 

四、镜面反射项

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 }
shader

 

效果图如下:

 

 转载请注明出处: http://www.cnblogs.com/jietian331/p/5549889.html

posted @ 2016-06-01 15:50  孤独の巡礼  阅读(2820)  评论(0编辑  收藏  举报