Carved Marker

Per Pixel Lighting [Part 1]

由於 DirectX 8 的推出,許多和 3D 相關的討論,也就轉移到 DirectX 8 的 pixel shader 上面。DirectX 8 的 pixel shader 功能相當強大,不過,到目前為止(12/2000),市面上還沒有任何顯示晶片是支援 DirectX 8 pixel shader 的。但是,這並不表示現在的顯示晶片就沒辦法支援 per pixel lighting,只不過,現在的顯示晶片所能表現的效果有限而已。

倒底什麼是 Per Pixel Lighting?簡單的說,就是指 lighting (即打光)的運算是以 pixel(即像點)為單位來做的,而不是以 vertex(即頂點)為單位。如果還不清楚的話,請記得 pixel 是指螢幕上形成畫面的最小單位的小點;而 vertex 則是指多邊形的頂點。舉個例子來說,一個三角形有三個頂點,但是畫在螢幕上的時候,它可能會包含很多個像點。所以,很明顯的,以像點為單位來計算打光的動作,比用頂點為單位,要來得精確得多;但是,它的運算量當然也大得多。

目前絕大部分的 3D 遊戲,在 dynamic lighting(動態打光,指光源可以任意移動的情形)的時候,都還是使用 per vertex lighting,也就是以頂點為單位的打光方式。如果是 static lighting,即光源不能移動的情形,則可以使用 light map 的方式來達到 per pixel lighting 的目的。Per vertex lighting 的方式,是在三角面的頂點上計算出打光的結果,而在繪製三角面的內部時,則是利用內插的方式來產生結果。如果三角面都不太大,這樣做的效果還算好。不過,如果三角面很大的話,那就不太好了。而且,這種內插的方式,會產生一種稱為 Mach band effect 的現象。下面是一些例子:

Vertex Lighting with no tessellation Per vertex lighting - 使用 6 個三角面
Vertex Lighting with 3 tessellation Per vertex lighting - 使用 54 個三角面
Vertex Lighting with 10 tessellation Per vertex lighting - 使用 600 個三角面

上面的三張圖,是由一個點光源來打光,打在三個互相垂直的平面上,且都是使用 per vertex lighting。在最上面的圖中,每個平面是由兩個三角面組成的。所以,每個平面只有四個頂點(兩個三角面共用兩個頂點)。這樣打光的效果很差,根本看不出有什麼效果。這是因為頂點的數目太少了。

在中間的圖,情形完全一樣,但是每個平面切成 9 個小正方形,共 18 個三角面。所以,每個平面有 16 個頂點。可以看得出來,打光的效果比上面的圖要好一些。但是三角面相接的地方卻變得很明顯。這就是 Mach band effect,是相當討厭的問題。會產生這個問題,主要是因為三角面內部是用內插的方式繪製的,所以三角面內部的亮度變化,就會比三角面相接處的亮度變化還小。而人的眼睛對亮度變化較大的地方,比變化小的地方更為敏感,所以才會使三角面相接的地方變得這麼明顯。

如果再增加頂點的數目,就會得到最下面的圖。最下面的圖是把每個平面切成 100 個小正方形,共 200 個三角面。所以每個平面共有 121 個頂點。因為三角面的數目非常多,所以每個三角面都很小,在這張圖中可能只包含不到 10 個像點。所以,它的效果會非常接近 per pixel lighting 的結果。和上面的圖相比,可以發現 Mach band effect 幾乎已經完全消失了,不過,若仔細看應該還是可以看到一些。

也許有人會認為,如果把頂點的數目增多,就可以達到接近 per pixel lighting 的效果,那何必還要 per pixel lighting 呢?就某些情形來說,這是對的。但是,對一般的情形來說,就沒有這麼順利了。因為觀察者的位置和光源的位置都很接近,所以當光源和觀察者都很接近某個平面時,它就需要更多的頂點。所以,這就需要動態計算需要的頂點個數。再加上,頂點的數目增加,就會讓 CPU 的運算量,也增加 bus 的負擔。

如果顯示晶片本身就有進行 per pixel lighting 的能力的話,根本就不需要增加三角面的個數,就可以達到很好的打光效果。不過,要達到完整的 per pixel lighting,需要支援 DirectX 8 pixel shader 的顯示晶片才行。但是,以目前一般的顯示晶片,只要支援 DOT_PRODUCT3 這個功能,還是做到某個程度的 per pixel lighting 的。

後面將會提到利用 DOT_PRODUCT3 來產生 per pixel lighting 的方法。

[Part 1] [Part 2] [Part 3] [Part 4] [Part 5] [Part 6] [Part 7]

12/14/2000, Ping-Che Chen


Sorry, Traditional Chinese only. This page is encoded in UTF-8.

Copyright© 2000 Ping-Che Chen