計算機圖形學基礎(五) 光照1
基礎就不記錄了,只記錄有關數學的東西
彩色光源
紅綠藍分量
環境光ambient
漫反射diffuse
鏡面反射specular
環境光
表徵場景中每一處的Ia都是相同的
點光源
理想的電光源向所有方面發射的光線強度都相等。
一個位於P0的點光源
點p從點光源接收到的光線強度(反比於光源到改點所在平面之間距離的平方)
僅利用點光源來照明往往會使場景的亮暗反差太大,可以看到,一些區域完全處於本影中,而另一些區域處於半影中。通過設定環境光,可以減弱由點光源照明引起的過高的對比度。
衰減因子實際應用中通常用形如
通過選擇常數a,b,c的值來獲得柔和的照明效果
聚光燈
限制點光源的發射光線來得到,如圖,如果角度為180,就是點光源。
更逼真的是通過其發光強度在圓錐內的分佈來描述,通常越接近圓錐中心,所發射光線的強度越大。通常定義為
指數e決定了隨著角度增大而衰減的速度
指數的影響
計算技巧:兩個單位向量的點積就是它們之間角度cos的值。
遠距離光源
非常遠。直接看作平行光源
用一個方向向量描述。
Phong反射模型
Phong反射模型用4個向量來計算表面上任一點p的顏色值。如果表面是曲面,那麼這4個向量都隨著表面上位置的不同而改變。
n:表面在p點處的發向量。
v:p指向觀察者(cop)的向量。
l:p指向擴充套件光源上任意一點的向量。
r:沿著向量l的方向入射的光線按照反射定律的出射方向。
Phong反射模型考慮了光線和材質之間的三種相互作用:環境光反射、漫反射、鏡面反射。
第i個光源的表示如下
rgb表示紅綠藍
ads表示環境光分量、漫反射光分量、鏡面反射光分量。
程式碼表示:
vec3 light_i_ambient, light_i_diffuse, light_i_specular;
//或者
vec4 light_i_ambient, light_i_diffuse, light_i_specular;
每個顏色分量在改點的反射率。
對於第i個光源的漫反射光的紅色分量Lird,可以計算出一個反射率Rird,於是前者對p點處光線強度的貢獻為RirdLird。
Rird的值取決於材質屬性、表面的方向、光源的方向以及光源與觀察者之間的距離。
第i個光源對p點處的紅色的光照強度。
p點處的紅色的光照強度。
某點的光照強度
程式碼表示:
vec4 reflect_i_ambient, reflect_i_diffuse, reflect_i_specular;
環境光反射
前面說過-所有點處的環境光強度都是相同的。
被反射的部分又環境光反射係數Ka確定,此時:
一個表面有3個環境光反射係數Kar,Kag,Kab。並且這3個反射係數可以不相同。
漫反射
理想的漫反射表面粗糙,以至向各個方向反射的光線強度都相等。有時被稱為Lambert表面,可以用Lambert定律來建模。
箭頭方向為光線方向。
可見Rd應該和cosθ成正比。cosθ可以通過兩個單位向量的點積來求。
法向量n和光源的方向l(參考前面的Phong模型)。
漫反射係數為Kd,如下公式很好推出
上面有一個問題,如果光源在水平面以下會取負值,此時希望取0
鏡面反射
高光。
觀察者看到的光線強度取決於理想反射器反射光線的方向r和觀察者的方向v這兩者之間的夾角。公式如下:
係數Ks大於等於0小於等於1,表示入射的鏡面反射光中有多大一部分被反射。指數α是高光係數。
無限大的α對應於鏡子,在100~500之間的α對應大多數金屬的表面,小於100的對應於高光區域比較大的材質。下列公式中rv代表的意思參照Phong模型。
包含衰減因子的Phong模型可以用下列來表示
改進的Phong模型
和Phong模型相比多了一個h,h就是l和v的中間向量,並且是一個單位向量(全部都是單位向量,為了方便運算)。
把Ψ稱為半形,h稱為半形向量。
一個簡單的證明可以得到2Ψ=Φ
如果把rv替換成nh,就無需計算r。半形Ψ比Φ小,為了減小對明暗繪製帶來的影響,改變指數使之更接近rv的e次方。至於在什麼情況下計算量會減少,這裡先不解釋了(先記錄基礎)。
這也被稱為Blinn-Phong模型。
下列使用改進的Phong模型繪製的一組Utah茶壺
計算向量
基本數學知識,只寫個大概
(1)法向量
1、不共線的三個點,它們分成2個向量的叉積確定法向量,注意叉積中的順序確定方向。
2、梯度向量,高數那門課最開始的,對x、y、z求導。
3、引數形式,同樣求導。
在OpenGL中,通常把法向量設定為頂點的屬性
typedef normal vec4;
normal n = vec4(nx, ny, nz, 0.0);
反射角
下圖字母代表的具體意思看前面的Phong模型,這裡直接寫推導。
αβ
r=αl+βn
nr=αln+β=ln
1=rr=α平方+2αβln+β平方
然後得到r=2(ln)n-1
我推了好久都沒推出來。。。看圖推得話很快就能推出來。
下面都只是簡單介紹
遞迴生成球面
從一個四面體,取每條邊中點,中點歸一化,遞迴。
然後就出來個單位球了。拓展半徑r的球很簡單,歸一化改成歸r化。
注意逆時針方向朝外。
光源
程式碼如下,很好理解,前面說過很多了
color4 light_diffuse, light_specular, light_ambient;
//點光源,用齊次座標表示,最後一個是1
point4 light_position = vec4(1.0, 2.0, 3.0, 1.0);
//遠距離光源,最後一個是0
point4 light_position = vec4(1.0, 2.0, 3.0, 0.0);
//衰減模型前面已經說過了,包括常數項、線性項和二次項
float attenuation_constant, attenuation_linear, attenuation_quadratic;
\\其他光源通過設定相應項,可以把點光源轉換到目的光源,前面已經解釋過。
材質
//假定物件表面是不透明的,通過指定三個顏色物件來指定3個係數。
color4 ambient = color4(0.2, 0.2, 0.2, 1.0);
color4 diffuse = color4(1.0, 0.8, 0.0, 1.0);
color4 specular = color4(1.0, 1.0, 1.0, 1.0);
//鏡面反射還需要指定高光係數
float shininess;
//如果物件表面的正面和背面具有不同的反射屬性
color4 back_ambient, back_diffuse, back_specular;
//自發光(任何光源都不會影響自己的發光分量,自己的發光分量也不會影響任何其他的表面)
//只是為表面增加了一個固定的顏色值
color4 emission = color4(0.0, 0.3, 0.3, 1.0);
可以通過定義結構體或者類來定義材質
typedef struct materialStruct{
color4 ambient;
color4 diffuse;
color4 specular;
color4 emission;
float shininess;
}materialStruct;
//可以通過指標來訪問這些屬性
currentMaterial = &brassMaterials;