[Shader筆記]基礎光照模型 - 理論篇

“ shader development using Unity” + Unity shader 入門精要筆記

詹閔翔
Eric’s publication
Aug 13, 2019

--

p.s. 本篇文章使用大量圖解來解釋公式,且不含任何程式碼。

目錄:

1. 真實世界的光照(我們是如何看到這個世界的)
2. 電腦模擬的光照(電腦模擬光照的方式)
3. 標準光照模型

ㄧ、真實世界的光照

當我們看到紅色的物體,實際上是因為

1.物體反射了紅色的波長
2.物體吸收了其他波長
3.最後光線進入我們的眼中

二、電腦模擬的光照

如果想要模擬真實世界的光照環境,我們需要考慮三種物理現象

1.光線從光源發射出來
2.光線與場景裡物體相交
3.攝影機吸收從物體散射回來的光線

光源 — 輻照度:(Irradiance):

首先來聊聊光源的部分。光不是憑空產生,而是由光源發射出來。白天刺眼的陽光與你床頭邊溫暖的小檯燈,他們不僅產生光的原理不同,視覺上所呈現的亮度也不相同。因此我們需要一個數學工具將光的亮度給量化,於是我們有了__輻照度__。

_定義__ :
維基百科裡的解釋是「在光學裏,輻照度(irradiance)是電磁輻射入射於曲面時每單位面積的功率。」

__公式__:

Irradiance = light direction * Cosθ

先別急著走,我猜你看完時可能跟我一樣滿臉問號,所以我準備了簡單的理解方式(ゝ∀・)。

__簡單的理解方式__:

Step1 我們假設光源是像太陽光那樣的平行光

Step2 但與物體接觸時光線與接觸面並不總是垂直

Step3 我們先假設不管是什麼樣的光,光線之間的距離都是一樣的

Step4 雖然光線之間的距離都相同,但不同傾斜程度的光線他們的垂直通過量卻不同於完全垂直的

以下是最直白的理解方式

直覺的理解方式

光與物體的交互 — 吸收和散射

在前面的示例中提到了,我們之所以能看到紅色的物體是因為,紅色物體的表面反射了紅色的波長,並吸收了其他大部分的波長,由此可知當光與物體相交時通常會有兩個結果

吸收(absorbtion):使光的密度(強度)、顏色被改變。
散射(scattering):使光行進方向發生改變,其中散射還可以再細分成

折射(refration)/ 透射(transmission) :將光散射到物體內部。
反射(reflection):將光散射到物體外部。

紅色的線條代表原來的光線,綠色的線條代表反射的光線,藍色的線條代表折射的光線

對於半透明物體,折射進入物體內部的光線會繼續與物體內部的顆粒相交並發生散射,而其中一部分光會重新射出物體表面,另一些則被物體吸收,最終重新射出的光繪具有與入社光不同的分佈與顏色。

為了近似模擬這個物理現象,標準光照模型了使用三個部分來分別呈現。分別是:

高光反射(Specular):描述物體是如何反射光線。
漫反射(diffuse):表示多少光線會被吸收、折射、散射出物體表面。
出射度(exitance):計算出社的光線、方向。

著色 — 攝影機吸收散射回來的光線,並最終畫出螢幕上的圖案。

根據材質屬性(也就是上面列出的高光反射、漫反射、出射度)以及光源信息(光源方向、輻照度、光源顏色…)使用一個等式去計算,並將最終結果呈現在螢幕上,而這個等式就是BRDF(Bidirectional Reflectance distribution Function)。

當給定模型表面上的一個點時,BRDF可以給出在某個出射方向上的光照能量分佈。在這裡我們只涉及到粗略的簡化模型,有興趣對BRDF做更深入理解的話,可以點進去看看底下這篇文章。

三、標準光照模型

在標準光照模型中,把進入到攝影機的光分為四個部分

環境光(Ambient)
自發光(Emissive)
漫射(Diffuse)
高光反射(Specular)

環境光 Ambient

在標準光環境模型中,我們使用一種稱為環境光的部分來近似模擬間接光源,間接光源指的是在多個物件中反射最後進入攝影機的光。

自發光 Emissive

光線也可以直接由光源進入攝影機而不需要經過反射,標準光源模型使用材質中的自發光參數來計算。

漫射 Diffuse

1. 計算公式

漫射用來模擬我們看到物體的顏色。

2. 公式解析:

光源顏色和材質漫反射顏色的混和,詳細的數學計算原理可以參考底下這篇

如下圖,如果光線從正面射入,則反射的光和法線所成的夾角最大為90度。

這邊我們要回憶起上面關於輻照度的解釋,當光線與法線平行時的光源亮度必然最亮,兩 單位向量 的內積其結果為底下

當cos在90度到-90度時值域在0~1之間,因此在這裡代表的是光線的強度
p.s. 會加一個max是因為要過濾掉從反面射過來的光

高光反射 Specular

高光反射用來模擬我們在平滑表面的物體上看到的亮點讓物體看起來是有光澤的。計算高光反射時我們需要知道的資訊比較多,有表面法線、光源方向、攝影機方向、反射向量,其中反射向量可以利用前三個向量求出,底下為證明過程:

這樣我們就有全部的參數了,這裡必須先說明一下,底下的高光反射模型是一種經驗模型,並不完全符合現實中的情況,一般來說我們會使用Phong模型、Blinn模型來近似模擬高光反射的現象。

1.Phong模型 :

首先我們看到公式的第一個括號,這邊與漫反射時一樣都是做顏色的混和

接著是公式的第二個部分,這邊做觀察方向與反射方向的內積來求高光反射的強度,max 則是防止內積結果為負值。頭上加的Mgloss是材質的光澤度,該值控制高光反射的亮點,值越大亮點就愈大,需要特別注意的是Mgloss不能為0,不然會整區都是亮點。

2.Blinn模型 :

Blinn模型的出現是為了減少Phong模型的計算過程,事實證明如果攝影機和光源距離足夠遠時Blinn模型會快於Phong模型。

Blinn模型引入了一個新的參數:向量h ,其計算方式為

不曉得大家會不會跟我一樣好奇,為什麼新的向量h可以用來求高光反射的亮度強度?原因是因為「如果反射方向趨近於觀察方向的話,則光源方向+觀察方向的正規化向量會非常接近法向量」,因此我們可以利用這個方式來避免需要大量計算過程的反射方向r。

下一篇文章我將會更新如何在Unity Shader中實現漫反射光源模型~
喜歡的話請記得幫我按個讚和分享喔,我們下次見 (*´▽`)ノシ

--

--

詹閔翔
Eric’s publication

現職專案管理與RD部門經理。畢業於國立台北科技大學 互動設計系。專注於各種可能的技術解決方案,喜歡從技術的角度解決問題,也喜歡接觸各種新科技跟open source專案與時代一起進化,並樂於將所見所聞製作成人人都能輕鬆理解的教學文章分享於網路平台。目前主力為軟體架構工程與系統開發