1. 程式人生 > 其它 >GAMES101-08- Shading 2(Shading,Pipeline and Texture Mapping)

GAMES101-08- Shading 2(Shading,Pipeline and Texture Mapping)

Shading 2(Shading,Pipeline and Texture Mapping)

高光(Specular Term)

光滑的平面通常會出現鏡面反射,當觀察方向與鏡面反射方向接近的時候就能看到高光。

高光向量與光源向量是以法線為對稱軸對稱的。

Blinn-Phong模型計算高光的能量

Blinn-Phong模型引入光源向量\(\vec l\)和觀測向量\(\vec v\)的半程向量\(\vec h\)來方便計算。一定程度上,\(\vec h\)\(\vec n\)接近,能反映\(\vec v\)(觀察方向)和\(\vec R\)(鏡面反射方向)的接近。而觀察方向與鏡面反射方向越接近,所看到的高光效果越強。

當然也可以直接用\(\vec v\)\(\vec h\)的接近來表示公式,那就是Phong模型。而Blinn-Phong模型是Phong模型的改進,因為Blinn-Phong的半程方量更好算些。

所以Blinn-Phong就巧妙地得到表示高光強弱的公式:

\[L_s=k_s(I/r^2)max(0,cosα)^p=k_s(I/r^2)max(0,\vec n \cdot \vec h)^p \]

按道理Blinn-Phong模型考慮了光的到達量\(k_s(I/r^2)\),也應該考慮光的吸收量\(max(\vec l \cdot \vec n)\),但Blinn-Phong模型為簡化模型,就沒有考慮物體吸收能量的部分了。

為什麼要引進指數p?

答:下面的函式影象是帶有指數的餘弦函式的值。可以看出,對於cosα,結果值都非常大,這樣高光就範圍特別廣,這是不合理的。因為我們希望高光都是集中在很小的區域裡的。因此我們要引入懲罰項指數p。比如觀察\(cos^{64}α\)的值就比較合理了,這樣的話只要\(\vec v\)\(\vec h\)偏離一點就不算它在高光範圍內,這樣就實現了高光集中在很小的區域內。(正常情況下,p的範圍在100~200)

下圖給出了高光係數\(k_s\)\(p\)值(給出了高光和漫反射都存在的觀測結果)發生變化時的球體觀測情況:

環境光(Ambient Term)

環境光的相關定義

①環境光與光照方向和觀測向量無關。
②環境光是一個常數

(是某一種顏色)。
③本節學的環境光計算是一種簡化的計算。

Blinn-Phong反射模型

Blinn-Phong反射模型的單點著色=環境光著色+漫反射著色+高光著色

著色頻率(Shading Frequencies)

著色頻率是指對某一片大小區域著色,考慮的是面。下面是三種不同著色頻率對應的觀察結果。

左圖,一個平面就做了一次著色。

中圖,一個頂點就做了一次著色。

右圖,一個畫素就做了一次著色。

三種不同著色頻率的著色模型

Flat Shading

逐三角形進行著色,每個三角形顏色一致。

Gouraud Shading

逐頂點進行著色,每個三角形內根據三個頂點進行插值著色,看起來比較平滑。

Phong Shading

逐畫素點進行著色。

三種著色模型的對比

如果模型的頂點/面越多,三種著色模型的差距會變小直至相同。(當然不太複雜的模型,還是Phong著色效果更好些)
模型越複雜,前兩種著色模型的效果會增強,但同時開銷也會越大。

如果三角形面數多於了畫素數,flat的工作量甚至會小於phong

如何計算頂點的法線

考慮如上的模型

  • 方法一:通常一個頂點都會屬於多個平面,對這些平面的法線之和求平均即可得到頂點的法線

當然每個平面多佔比重不同,比如上圖中法線\(\vec N_2\)所在平面比較小,法線\(\vec N_3\)所在平面比較大,那麼對於頂點法線的貢獻也會更大一些。

所以,根據各個面的面積進行加權平均,效果會更好。

如何計算畫素的法線

假設我們已知兩側的頂點法線,如下圖中間的法線就是順著法線方向一一排開(注意,所有的法線都是反向,所以要對所有的頂點法線都進行歸一化處理變成單位向量,保證它們的長度相同)。

給出頂點的法線,怎麼樣計算出中間的插值法線呢?

答:使用重心座標可以進行計算得到內部的各個點的法線。

管線(Pipeline)

管線指的是從模型到畫素的整個繪製流程,可以看成是從模型到繪製成圖的一個流水線。管線分為以下幾步:

頂點處理\(\rightarrow\)三角形處理\(\rightarrow\)光柵化\(\rightarrow\)畫素處理\(\rightarrow\)混合所有的畫素成一張影象
注意
如果著色模型是Phong Shading,則著色步驟是在畫素處理環節進行;

如果著色模型是Gouraud Shading,則著色操作可以在頂點處理環節進行。

Shader Programs

現在的GPU支援自己編寫頂點或者畫素的著色程式。

在Shader裡面只需要管一個頂點或者畫素就行,定義頂點著色器或者畫素著色器。

下圖是簡單的OpenGL的著色語言GLSL的畫素著色器的小程式:

推薦網站shadertoy:https://www.shadertoy.com/view/ld3Gz2

只需要定義好著色器,將程式寫出來後在網頁上就能看到對應的結果。

紋理對映(Texture Mapping)

我們希望定義在物體不同位置定義不同屬性,根本上就是定義任何一個點的不同的基本屬性。

紋理對映

任何一個三維物體的表面其實是二維的。那麼我們可以把紋理定義為一張圖。
紋理對映:在物體表面應用紋理可以理解為是對其進行貼圖。找到物體上的一個點跟紋理上的點的關係。

紋理座標系

我們知道紋理應該怎麼“貼圖”,是因為我們知道三角形對應的紋理座標。也就是說我們需要定義了一個紋理座標系(u, v)。每個三角形都對應紋理座標系上的一個位置,實際的紋理對映結果如下:

而不同位置也可以對映到同一紋理,也就是說紋理可以被重複使用,如下圖的地面部分,紋理就被重複使用了。

從上圖可以看出,紋理之間有個非常明顯的縫隙,而想要紋理無縫銜接(tiled)的合成是很困難的,需要各種各樣的演算法。這裡就是簡單提一下。

回到上面紋理對映的話題,我們已經知道三角形三個頂點對應的紋理座標(u,v),那麼我們怎麼知道三角形內部各個點對應的紋理座標(u,v)呢?如何實現三角形內部的平滑過渡?

答:這又涉及到插值問題,跟重心座標相關,下節課解釋。