光照計算

首先我們將要了解如下問題
1. 學習Direct3D支持的光照資源, 以及它們照射出的燈光類型
2. 弄懂怎樣定義燈光去影響其照射的表面
3. 找出怎樣算出描述三角形的方向以便我們能夠確定光線照射到三角形的角度

我們在這裏將融合《3D遊戲編程大師技巧》和《Direct3D》的部分內容。
即, 將它們一一映射。

顏色模型和材質
   物體的材質決定了它將如何於光線交互, 材質用來描述物體被光線照射後將對光線產生何種影響。學習過物理課, 我們知道不同材料,或者說不同的原子對光子產生不同的影響。
這裏說,也許不是那麼容易理解, 我們還是來看看究竟光是什麼吧。
首先我們回顧下光的基本的特性:
一、 光可以沿着直線傳播
二、 光會發生折射
三、 光會發生反射
四、 光會發生色散
五、 光會發生干涉
六、 光會發生衍射
七、 光是一種電磁波
八、 光存儲偏振
九、 光的高聚合形態-激光
十、 光電效應和光子
十一、 光即是波又是粒子

看, 我們的高中物理部分所講解的光的現象有這麼多有關光的特性。
下面我們將簡述光的特性, 並聯系如何聯繫到用Direct3D表達出來。

能夠發光的物體叫做光源(Light Source). 太陽就是一個巨大的自然光源。
而到了夜晚人們不得不自己製作人造光源。人造光源有火把。蠟燭,電燈
等等。 根據光源發射光的不同性質, 我們可以將光源簡單的歸類:
一、 定向光源
  定向光源是沒有確切位置的光源, 它離場景非常遠, 其光線平行第照射到表面(surface)上, 這種光源也被稱爲無窮遠光源。定向光源的特徵是其光照強度(Light Intensity)不會隨距離而衰減, 這是因爲光線已經傳播了無窮遠的距離。 定向光源本身也有強度和顏色。要定義定向光源, 只需指定其初始顏色和強度即可。爲了表示光源的光照強度我們有這麼個公式:
I(d)dir = I0dir * Cldir  ( 光照強度 = 初始光源強度 * 光源顏色 )
I0dir  -  表示初始光源強度,  Cldir 表示光源的顏色,  I(d)dir 表示將產生目標光的光照強度。 那麼Direct3D中如何表示呢?
首先我們來看一個結構, 我們以Direct3D9爲主: 
typedef struct _D3DLIGHT9 {
    D3DLIGHTTYPE Type; //光源的類型
    D3DCOLORvalue Diffuse; //光源發出的漫射光顏色
    D3DCOLORvalue Specular; //光源發出的鏡面反射光顏色
    D3DCOLORvalue Ambient; //光源發出的環境光顏色
    D3DVECTOR Position;          //光源的位置, 只對點光源和聚光燈有效
    D3DVECTOR Direction; //光源的方向
    float Range; //光照射的範圍
    float Falloff;                //對聚光燈有效,表示內錐到外錐之間的光照強度衰減,通常爲1.0f
    float Attenuation0;           //對點光源和聚光燈有效
    float Attenuation1; //對點光源和聚光燈有效
    float Attenuation2; //對點光源和聚光燈有效
    float Theta;                  //只用於聚光燈,指定內錐的角度,單位是弧度
    float Phi;                    //只用於聚光燈,指定外圓錐的角度,單位是弧度
} D3DLIGHT9;
這個結構用來存儲光的屬性
那麼, 我們就利用這個結構來定製出不同的光源類型,其中D3DLIGHTTYPE Type; 有三種不同取值分別和點光源,定向光源,聚光燈一一對應,分別爲:D3DLIGHT_POINT, D3DLIGHT_DIRECTIONAL,  D3DLIGHT_SPOT. 
定向光源最直接的現實例子就是我們的太陽, 它離地球非常遠, 它的光線平行的照射到地球表面上,它的光不衰減。
二、 點光源
 點光源用來表示實際生活中的電燈等形狀像點一樣的光源, 其光照強度隨光源離表面S的距離衰減, 衰減使用三個因子來模擬, 常量衰減因子(kc)、線性衰減因子(kl)和二次衰減因子(kq)  用d (distance)表示位於點p處的點光源和表面S上的點s之間的距離, 光照強度和距離的關係如下
  I(d)point = I0point * Clpoint  /  kc + kl * d + kq * d^2
其中 d = |p-s|
Andre LaMothe在實際應用中,發現不包含二次項的更簡單的光源模型也很好使:
I(d)point = I0point * Clpoint  /  kc + kl * d;
三、 聚光燈
  聚光燈的現實例子可以認爲是手電筒,我們家唯一的家用電器。或者類似於手電筒的發光設備, 比如探照燈, 它們的特徵是, 當光源將光線投射到表面時,會形成內錐和外錐。其中內錐的光照強度高一些,並逐步向外錐衰減。由於聚光燈複雜很多,所以在實時遊戲中, 非常粗略地模擬聚光燈的模型就能滿足需要。 我們使用簡化後的公式:
I(d)spotlight = I0spotlight*Clspotlight * MAX(cosθ,0)^pf  / kc + kl*d + kq*d^2
其中 d = |p-s| pf 爲指數因子。

瞭解了三種基本光源類型後, 我們來看看前面沒有展開的話題:
一、 光可以沿着直線傳播
光在空氣中沿着直線傳播, 在水、玻璃等透明物質中的傳播路線也是直的。
所以我們把光的傳播方向的直線叫做光線(ray)。但是光線必須在均勻的介質中才沿着直線傳播, 如果介質不均勻光線也會發生彎曲。例如地球周圍的大氣就是不均勻的。所以我們可以說 光在均勻介質中是沿着直線傳播的。如果瞭解了引力的作用,我們也可以說在一般引力環境下,光線將沿着直線傳播,如果在強引力作用下光線也將發生彎曲。
二、 光會發生折射(refraction)
光從一種介質斜射入另一種介質(medium)時, 傳播方向一般會發生變換, 這種現象叫做光的折射。前面說過光從不均勻的空氣中傳播路徑是彎曲的, 實際上這也是折射現象。
折射光線和入射光線分居法線兩側, 當入射角不和介質表面垂直時傳播方向將改變。當垂直時,傳播方向不變。
三、 光會發生反射
  從光的入射點O 所做的垂直於鏡面的線ON叫做法線, 入射光線與法線的夾角叫做入射角, 反射光線與法線的夾角叫做反射角。
  光的反射可以分爲鏡面反射(Specular reflect)和漫反射(Diffuse reflect)
  鏡面很光滑, 射到平面鏡上的平行光線反射後仍然是平行的。光滑鏡面的反射叫做鏡面反射。
一個凹凸不平的物體的表面被光線照射會發生漫反射(Diffuse reflect)。
不同介質的折射率不同, 我們把折射率較小的介質稱爲光疏介質(medium) , 折射率較大的介質稱爲光密介質。光疏介質和光密介質是相對的, 比如拿水、水晶和金剛石三種物質比較, 水晶對水來說是光密介質。對金剛石來說是光疏介質。當入射角達到一定程度,使折射角達到90度時,折射光完全消失, 只剩下反射光, 這種現象叫做全反射。
可見,很多時候光線的折射現象和反射現象是交互(interactive)發生的, 隨時將因爲入射角的改變而導致僅反射, 即反射又折射。
四、 光會發生色散
  棱鏡也叫三棱鏡。 楞鏡可以改變光的傳播方向還可以使光發生色散。太陽、日光燈等發出的光, 沒有特定的顏色, 叫做白光。一條光線照射到棱鏡上,我們預期會看到白色亮線,但是實際上卻出現了許多不同顏色的亮線。這條亮帶叫做光譜。 這個現象說明白光實際上是由各種單色光組成的複色光。複色 在介質中由於折射率不同分解成單色光的現象, 叫做光的色散。
五、 光會發生干涉
  我們現在已經知道,光即是李子又是電磁波,可以這樣理解,光粒子沿着波動軌跡運動。那麼我們先看由於光發生干涉而說明光是一種波的現象。首先我們看波的干涉。頻率相同的兩列波疊加, 使某些區域的振動加強, 某些區域的振動減弱, 而且振動加強的區域和振動減弱的區域相互隔開。 這種現象叫做波的干涉。 1801年,英國物理學家托馬斯 楊在實驗室裏成功第觀察到了光的干涉。 光發生干涉現象時, 光在一些地方互相加強, 在另一些地方互相削弱。
六、 光會發生衍射
  光的衍射, 波的衍射現象, 波可以繞過障礙物繼續傳播, 這種現象叫做波的衍射。
由於光的波長很短, 所以一般我們看不到光的衍射現象。 而當光射向一個針孔、一條狹縫、一根細絲時, 可以清楚地看到光的衍射現象。
七、 光是一種電磁波
  光的衍射和干涉證明了光是一種波。19世界60年代,麥克斯韋預先了電磁波的存在,並從理論上得出, 電磁波在真空中的傳播速度應爲3.11x10^8m/s, 而當時實驗測得的光速爲3.15x10^8m/s, 所以他認爲這不是一種巧合, 它表明光與電磁現象之間有本質的聯繫。由此它提出光的本質上是一種電磁波。後來經過赫茲的實驗證明光的速度和電磁波的速度確實相同, 這樣就證明了光的電磁說的正確性。
八、 光的偏振
  光的干涉和衍射現象說明光具有波動性, 但不能確定光究竟是橫波還是縱波。但是光的偏振現象說明, 光是橫波。 太陽、電燈等普通光源發出的光, 包含這垂直於傳播方向上沿一切方向振動的光, 而且沿着各個方向振動的光波的強度都相同。 這種光叫做自然光。 自然光通過偏振片P(叫做起偏器)之後, 只有振動方向跟偏振片的透振方向一致的光波(light-wave)才能通過。 也就是說, 通過偏振片P的光波, 在垂直於傳播方向的平面上, 只沿着一個特定的方向振動。 這種光叫做偏振光。 橫波只沿着某一個特定的方向振動, 稱爲波的偏振。
九、 光的高聚合形態-激光
  這種光非常好,我們經常期望在遊戲中實現激光效果。Laser
普通光源由於向各個方向發射的光是不確定的, 發光頻率也不一樣, 所以這樣的光叫非相干光。 只有頻率相同、並滿足一定條件的光纔是相干光。 激光是一種人工產生的相干光。
激光的平行度非常好, 可以傳播很遠的距離後仍能保持一定的強度。
激光的亮度高, 在很小的空間和很短的時間內集中很大的能量。即, 激光可以產生高溫高壓條件。
十、 光電效應和光子
  光電效應 – 在光照射下物體發射電子的現象, 叫做光電效應, 發射出來的電子叫做光電子。 最開始發現光電效應時物理學家們沒有感到驚奇, 認爲當光入射金屬時, 金屬裏的自由電子會由於變化着的電場的作用而振動。 如果光足夠強, 振幅足夠大, 不論光的頻率高低, 經過一段時間後電子的振幅就會很大, 就有可能飛出金屬表面。
但是進一步研究發現, 對各種金屬都存在着極限頻率和極限波長, 如果入射光的頻率比極限頻率低, 那麼無論光多強, 照射時間多長, 都不會發生光電效應。如果入射光頻率高於極限頻率, 即使光不強, 當它射到金屬表面時也會觀察到光電子的發射。
  光電效應具有瞬時性, 即無論光的亮度如何,只要高於極限頻率 光電子的產生都幾乎是瞬時的, 不超過10^-9s 
 1900年, 德國物理學家普朗克在研究物體熱輻射(radiation)的規律時發現, 只有認爲電磁波的發射和吸收不是連續的, 而是一份一份地進行的, 理論計算的結果才能跟實驗事實相符。這樣的一份能量叫做能量子。 普朗克還認爲每一份的能量子等於hv, 其中v是輻射電磁波的頻率, h是一個常量, 叫做普朗克常量。 h = 6.63x10^-34Js. 
 受普朗克啓發, 愛因斯坦於1905年提出, 在空間傳播的光也不是連續的, 而是一份一份的, 每一份叫做一個光量子, 簡稱光子。 E = hv
那麼 由於光本身是一種電磁波, 所以根據普朗克的結論, 光量子就是能量子。

好以上即濃縮了一份關於初中和高中關於光的特徵的常識。

光照計算是基於大量的面法線(face normal)的, 這要求我們必須根據預先計算好的法線來執行光照計算: 要麼在背面消除階段執行光照計算, 要麼在背面消除階段將法線存儲起來,以便在光照計算階段使用它們。

着色處理
 着色處理髮生在光柵化和指定圖元上的頂點顏色怎樣被計算成像素顏色之間。目前這裏有三種着色模式可用: 平面着色(float shading)和高洛德(Gouraud shading)。平面着色,圖元像素的顏色是均勻的, 且就是指定圖元第一個頂點的顏色。 因此一但三角形的第一個頂點被指定成紅色, 那麼它的其他三個頂點也將會是紅色。
高洛德着色, 圖元表面的顏色是由每個頂點通過線性插值來賦予。 
着色模式受Direct3D設置狀態決定。
IDirect3DDevice9::SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
IDirect3DDevice9::SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
IDirect3DDevice9::SetRenderState(D3DRS_SHADEMODE, D3DSHADE_PHONG);

光照首先要處理的如何定義光源, 如何執行着色, 如何定義材質。而紋理,材質(介質), 光照都可以看做是增強真實感的部分。
面法線(face normal) 是描述多邊形表面方向的一個向量。
頂點法線(Vertex normals)也是基於同樣的概念, 但是我們與其指定每個多邊形的法線, 還不如爲每個頂點指定。 

發佈了19 篇原創文章 · 獲贊 0 · 訪問量 3094
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章