3D數(shù)學(xué)-基礎(chǔ)光照

3D數(shù)學(xué)-基礎(chǔ)光照

好記性不如爛筆頭啊,還是記錄一下!


概述

我們要模擬真實(shí)的光照環(huán)境來(lái)生成一張圖像,需要考慮三種物理現(xiàn)象:

  • 首先,光線(xiàn)從光源(light source)中發(fā)射出來(lái)。
  • 然后,光線(xiàn)和場(chǎng)景中的一些物體相交: 一些光線(xiàn)被物體吸收了,而另一些光線(xiàn)被散射到其他方向。
  • 最后,攝像機(jī)吸收了一些光,產(chǎn)生了一張圖像。

下面,我們將對(duì)每個(gè)部分進(jìn)行更加詳細(xì)的解釋。


光源

在實(shí)時(shí)渲染中,我們通常把光源當(dāng)成一個(gè)沒(méi)有體積的點(diǎn),用l來(lái)表示他的方向。那么,我們?nèi)绾螠y(cè)量一個(gè)光源發(fā)射出了多少光呢?也就是說(shuō),我們?nèi)绾瘟炕饽??在光學(xué)里,我們通常用輻照度(irradiance)來(lái)量化光。對(duì)于平行光來(lái)說(shuō),它的輻照度可通過(guò)計(jì)算在垂直于l的單位面積上單位時(shí)間內(nèi)穿過(guò)的能量來(lái)得到。在計(jì)算光照模型時(shí),我們需要知道一個(gè)物體表面的輻照度,而物體表面往往時(shí)和l不垂直的,那么如何計(jì)算這樣的表面的輻照度呢?我們可以使用光源方向l和表面法線(xiàn)n之間的夾角的余弦值來(lái)得到。需要注意的是,這里默認(rèn)方向矢量的模都為1。

3D數(shù)學(xué)-基礎(chǔ)光照_1.png

由上圖可知輻照度是和照射到物體表面時(shí)光線(xiàn)之間的距離d/\cos\theta成反比的,因此輻照度就和\cos\theta成正比。\cos\theta可以用光源方向l和表面法線(xiàn)n點(diǎn)積來(lái)得到。這就是使用點(diǎn)積來(lái)計(jì)算輻照度的由來(lái)。

環(huán)境光源

環(huán)境光源也稱(chēng)為環(huán)境光,是一種低強(qiáng)度光源,由環(huán)境中所有相鄰表面的反射光產(chǎn)生。在真實(shí)世界中,物體可以被間接光照(indirect light)所照亮。光線(xiàn)通常會(huì)在多個(gè)物體間反射,最后進(jìn)入攝像機(jī),在進(jìn)入攝像機(jī)前,可能經(jīng)過(guò)了不止一次的物體反射。利用環(huán)境光可以近似表示場(chǎng)景中某一區(qū)域的大概亮度,而不用對(duì)場(chǎng)景中所有對(duì)象件的間接反射光進(jìn)行復(fù)雜的運(yùn)算。環(huán)境光的計(jì)算非常簡(jiǎn)單,它通常是一個(gè)全局變量。

平行光源

平行光源,也成為無(wú)窮遠(yuǎn)光源,是從無(wú)窮遠(yuǎn)處發(fā)出的某一方向的光的光源,平行光源特別誰(shuí)和模擬太陽(yáng)一類(lèi)的光,該光源發(fā)出的光線(xiàn)是平行的。該光源在有限的空中沒(méi)有具體的位置,照射范圍也是無(wú)限的,其強(qiáng)度不會(huì)隨著距離的增加而減弱。

點(diǎn)光源

點(diǎn)光源是從空間中一點(diǎn)向各個(gè)方向發(fā)出的等強(qiáng)度的光的光源。點(diǎn)光源發(fā)出的光的強(qiáng)度與傳播距離成反比自然衰減。

聚光燈光源

聚光燈光源除了有一個(gè)首選方向之外,其他特點(diǎn)與光源類(lèi)似,聚光燈光源發(fā)出的光的強(qiáng)度與傳播距離成反比自然衰減。


吸收和散射

光線(xiàn)由光源發(fā)射出來(lái)后,就會(huì)與一些物體相交。通常,相交的結(jié)果有兩個(gè):散射(scattering)吸收(absorption)。

散射只改變光線(xiàn)方向,但不改變光線(xiàn)的密度和顏色。而吸收只改變光線(xiàn)的密度和顏色,但不改變光線(xiàn)的方向。光線(xiàn)在物體表面經(jīng)過(guò)散射后,有兩種方向:一種將會(huì)散射到物體內(nèi)部,這種現(xiàn)象被稱(chēng)為折射(refraction)透射(transmission);另一種將會(huì)散射到外部,這種現(xiàn)象稱(chēng)為折射(refraction)。對(duì)于不透明物體,折射進(jìn)入物體內(nèi)部的光線(xiàn)還會(huì)繼續(xù)與內(nèi)部的顆粒進(jìn)行相交,其中一些光線(xiàn)最后會(huì)重新發(fā)射出物體表面,而另一些則被物體吸收。那些從物體表面重新發(fā)射出的光線(xiàn)將具有和入射光線(xiàn)不同的方向分布和顏色,如圖:

3D數(shù)學(xué)-基礎(chǔ)光照_2.png

為了區(qū)分不同的散射方向,我們?cè)俟庹漳P椭惺褂昧瞬煌牟糠謥?lái)計(jì)算它們:高光反射(specular)部分表示物體表面是如何反射光線(xiàn)的,而漫反射漫反射(diffuse)部分則表示有多少光線(xiàn)會(huì)被折射、吸收和散射出表面。根據(jù)入射光線(xiàn)的數(shù)量和方向,我們通常使用出射度(exitance)來(lái)描述它。輻照度和出射度之間是滿(mǎn)足線(xiàn)性關(guān)系的,二它們之間的比值就是材質(zhì)的漫反射和高光反射屬性。


著色

著色(shading)指的是,根據(jù)材質(zhì)屬性(如漫反射屬性等)、光源信息(如光源方向、輻照度等),使用一個(gè)公式去計(jì)算沿某個(gè)觀(guān)察方向的出射度的過(guò)程。我們也把這個(gè)公式稱(chēng)之為光照模型(Lighting Model)不同的光照模型有不同的目的。例如,一些用于描述粗糙的物體表面,一些用于描述金屬表面等。


光照模型

BRDF光照模型

我們已經(jīng)了解了光線(xiàn)在和物體表面相交時(shí)會(huì)發(fā)生那些現(xiàn)象,當(dāng)已知光源位置和方向、視角方向,我們就需要知道一個(gè)表面是如何和光照進(jìn)行交互的。例如,光線(xiàn)從某個(gè)方向照射到一個(gè)表面時(shí),有多少光線(xiàn)被發(fā)射?反射的方向有哪些?而BRDF(Bidirectional Reflection Distribution Function)就是用來(lái)回答這些問(wèn)題的。當(dāng)給定模型表面上的一點(diǎn)時(shí),BRDF包含了對(duì)該點(diǎn)外觀(guān)的完整的描述。在圖形學(xué)中,BRDF大多數(shù)使用一個(gè)數(shù)學(xué)公式來(lái)表示,并且提供了一些參數(shù)來(lái)調(diào)整材質(zhì)屬性。通俗來(lái)講,當(dāng)給定入射光線(xiàn)的方向和輻照度后,BRDF可以給出在某個(gè)出射方向上的光照能量分布。

標(biāo)準(zhǔn)光照模型

標(biāo)準(zhǔn)光照模型是對(duì)真實(shí)場(chǎng)景進(jìn)行理想化和簡(jiǎn)化后的模型,也就是說(shuō)它們并不能真實(shí)地反映無(wú)敵和光線(xiàn)之前的交互,是一種經(jīng)驗(yàn)?zāi)P?。?biāo)準(zhǔn)光照模型只關(guān)心直接光照(direct light),也就是那些直接從光源發(fā)射出來(lái)照射到物體表面后,經(jīng)過(guò)物體一表面的一次反射直接進(jìn)入攝像機(jī)的光線(xiàn)。

它的基本方法是,把進(jìn)入到攝像機(jī)內(nèi)的光線(xiàn)分為4個(gè)部分,每個(gè)部分使用一種方法計(jì)算它的貢獻(xiàn)度。這4個(gè)部分是:

1.環(huán)境光(ambient)

這里我們使用c_{ambient}來(lái)表示,這個(gè)部分用于描述該表面的所有間接光照。由于環(huán)境光通常是一個(gè)全局變量:

c_{ambient}=g_{ambient}

2.自發(fā)光(emissive)

這里我們使用c_{emissive}來(lái)表示,這個(gè)部分用于描述給定一個(gè)方向時(shí),一個(gè)表面本身會(huì)想該方向發(fā)射多少輻射量。這里我們需要計(jì)算直接由發(fā)光體表面進(jìn)入攝像機(jī)的光線(xiàn)。它的計(jì)算也很簡(jiǎn)單,就直接使用了該材質(zhì)的自發(fā)光顏色:

c_{emissive}=m_{emissive}

3.漫反射(diffuse)

這里我們使用c_{diffuse}來(lái)表示,這個(gè)部分用于描述從光源照射到模型表面時(shí),該表面會(huì)向每個(gè)方向散射多少輻射量。由于是向各個(gè)方向散射的輻射度,所以在漫反射中,視角的位置是不重要的,應(yīng)為反射是完全隨機(jī)的,因此可以認(rèn)為在任何反射方向上的分布都是一樣的。但是,入射光線(xiàn)的角度很重要。

蘭伯特光照模型

漫反射符合蘭伯特定律(Lambert's law):反射光線(xiàn)的強(qiáng)度與表面法線(xiàn)和光源方向之間夾角的余弦值成正比。因此漫反射部分的計(jì)算如下:

c_{diffuse}=(c_{light} \cdot m_{diffuse}) \cdot max(0, n \cdot l)

其中n是表面法線(xiàn),l是指向光源的單位矢量,m_{diffuse}是材質(zhì)的漫反射顏色,c_{light}是光源顏色和強(qiáng)度。需要注意的是,我們需要防止法線(xiàn)和光源方向點(diǎn)乘的結(jié)果為負(fù)值,這樣可以防止物體被從后面來(lái)的光源照亮。

半蘭伯特光照模型

蘭伯特光照模型有一個(gè)問(wèn)題是,在光照無(wú)法到達(dá)的區(qū)域,模型的外光通常是黑的,沒(méi)有任何的明暗變化,這會(huì)使模型的背光區(qū)域看起來(lái)就像一個(gè)平面一樣,失去了模型細(xì)節(jié)的表現(xiàn)。為此,有一種改善技術(shù)被提出來(lái),這就是半蘭伯特(Half Lambert)光照模型。Valve公司在開(kāi)發(fā)游戲《半條命》時(shí)提出了改善方案,在原蘭伯特光照模型上進(jìn)行了一個(gè)簡(jiǎn)單的修改,廣義的半蘭伯特光照模型的公式如下:

c_{diffuse}=(c_{light} \cdot m_{diffuse})( \alpha (n \cdot l) + \beta )

絕大多數(shù)情況下\alpha\beta的值都是0.5,即公式為:

c_{diffuse}=(c_{light} \cdot m_{diffuse})(0.5*(n \cdot l)+0.5)

通過(guò)這樣的方式,我們可以把n \cdot l的結(jié)果范圍從\left [ -1,1 \right ]映射到\left [ 0,1 \right ],因此模型的背光區(qū)域也可以有敏感變化,不同的點(diǎn)積結(jié)果會(huì)映射到不同的值上。實(shí)際上半蘭伯特光照模型沒(méi)有任何的物理依據(jù),它僅僅是一個(gè)視覺(jué)加強(qiáng)技術(shù)。

4.高光反射(specular)

Phong光照模型

這里我們使用c_{specular}來(lái)表示,這個(gè)部分用于描述從光源照射到模型表面時(shí),該表面會(huì)在完全鏡面反射方向散射多少輻射量。這也是一種經(jīng)驗(yàn)?zāi)P?,并不符合真是世界中的高光反射現(xiàn)象。它可用于計(jì)算那些沿著完全鏡面反射方向被反射的光線(xiàn),這可以讓物體看起來(lái)是有光澤的,例如金屬材質(zhì)。

計(jì)算高光反射需要知道的信息比較多,如表面法線(xiàn)、視角方向、光源方向、反射方向等。在本節(jié)中,我們假這些矢量都是單位矢量。這四個(gè)矢量中,我們只要知道其中前三個(gè)矢量即可,而第四個(gè)矢量——反射方向可以通過(guò)計(jì)算獲得:

3D數(shù)學(xué)-基礎(chǔ)光照_3.png

N是表面法線(xiàn),L是指向光源的矢量,R為反射方向,根據(jù)圖中可知:

L - R = X

LN上的投影為N \cdot L, 則投影的矢量為(N \cdot L)N,則有以下關(guān)系式:

X = 2(L-(N \cdot L)N)

X代入之前的式子可得:

R = L - X = L - 2(L-(N \cdot L)N) = 2(N \cdot L)N - L

解決了反射方向的計(jì)算,我們就可以利用Phong模型來(lái)計(jì)算高光反射了,如圖:

3D數(shù)學(xué)-基礎(chǔ)光照_4.png

公式為:

c_{specular}=(c_{light} \cdot m_{specular}) \cdot max(0, v \cdot r)^{m_{gloss}}
其中m_{gloss}是材質(zhì)的光澤度(gloss),也被稱(chēng)為反光度(shininess)。它用于控制高光區(qū)域的“亮點(diǎn)”有多寬,m_{gloss}約大,亮點(diǎn)就越小。m_{specular}是材質(zhì)的高光反射顏色,它用于控制改材質(zhì)對(duì)于高光反射的強(qiáng)度和顏色。c_{light}是光源顏色和強(qiáng)度

Blinn-Phong光照模型

Phong光照模型能夠很好的表現(xiàn)高光效果,不過(guò)Phong光照模型的缺點(diǎn)就是計(jì)算量較大。針對(duì)這個(gè)問(wèn)題,Blinn提出了一個(gè)簡(jiǎn)單的修改方法來(lái)得到類(lèi)似的效果。它的基本思想是,避免計(jì)算反射方向r,為此,Blinn-Phong光照模型引入了一個(gè)新的矢量h,它是通過(guò)對(duì)vl的取平均后在歸一化得到的。即:

h = \frac{v+l}{\vert v+l \vert}

然后使用nh之間的夾角進(jìn)行計(jì)算,而非vr之間的夾角,如圖:

3D數(shù)學(xué)-基礎(chǔ)光照_5.png

公式為:

c_{specular}=(c_{light} \cdot m_{specular}) \cdot max(0, n \cdot h)^{m_{gloss}}

在一般情況下,Blinn-Phong光照模型效率會(huì)更高。


著色模型

有了上面的基本光照模型的計(jì)算公式,那么我們?cè)谀睦镉?jì)算這些光照模型呢?通常來(lái)講我們有以下兩種:

逐頂點(diǎn)光照(per-vertex lighting)

逐頂點(diǎn)光照(per-vertex lighting)也被稱(chēng)為高洛德著色(Gouraud shading)。在逐頂點(diǎn)光照(per-vertex lighting)中,我們?cè)诿總€(gè)頂點(diǎn)上計(jì)算光照,然后會(huì)在渲染圖元內(nèi)部進(jìn)行線(xiàn)性插值,最后輸出成像素顏色。由于頂點(diǎn)數(shù)目往往遠(yuǎn)遠(yuǎn)小于像素?cái)?shù)目,因此計(jì)算量往往要小于逐像素光照(per-pixel lighting)。但是,由于逐頂點(diǎn)光照(per-vertex lighting)依賴(lài)于線(xiàn)性插值來(lái)得到像素光照,因此,當(dāng)光照模型中有非線(xiàn)性的計(jì)算(例如計(jì)算高光反射(specular))時(shí),逐頂點(diǎn)光照就會(huì)出問(wèn)題,由于逐頂點(diǎn)光照(per-vertex lighting)會(huì)在渲染圖元內(nèi)部對(duì)頂點(diǎn)顏色進(jìn)行插值,這會(huì)倒是渲染圖元內(nèi)部的顏色總是暗于頂點(diǎn)處的最高顏色值,這在某些情況下會(huì)產(chǎn)生明顯的棱角現(xiàn)象。

逐像素光照(per-pixel lighting)

逐像素光照(per-pixel lighting)也被稱(chēng)為Phong著色(Phong shading),在逐像素光照(per-pixel lighting)中,會(huì)以每個(gè)像素為基礎(chǔ)得到它的法線(xiàn)(可以是對(duì)頂點(diǎn)法線(xiàn)插值得到的,也可以是從法線(xiàn)紋理中采樣得到的),然后進(jìn)行光照模型的計(jì)算。與之前提到的Phong光照模型不同,這種在面片之間對(duì)頂點(diǎn)法線(xiàn)插值的技術(shù)稱(chēng)為逐像素光照(per-pixel lighting)或者Phong著色(Phong shading)。


本節(jié)教程就到此結(jié)束,希望大家繼續(xù)閱讀我之后的教程。

謝謝大家,再見(jiàn)!


飲水思源

參考文獻(xiàn):

《3D游戲與圖形學(xué)中的數(shù)學(xué)方法》

《Unity Shader 入門(mén)精要》


版權(quán)聲明:原創(chuàng)技術(shù)文章,撰寫(xiě)不易,轉(zhuǎn)載請(qǐng)注明出處!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容