陰影體
陰影體(陰影錐)是三維計算機圖形中所使用的一種技術,始於1977年,用於在繪製的場景中加入陰影。它通常被認為是現代三維圖形硬件的能力下的最實用的通用實時陰影系統之一,並已隨着毀滅戰士3而流行開來。
陰影體將虛擬世界分成兩部分;在某光源的陰影中的部分和不在陰影中的部分。
構造
編輯要構造一個陰影體,先從光源投射一條射線穿過產生陰影的物體中的每個頂點到某個點(通常在無窮遠點)。這些射線一起組成一個體;每個該體中的點都在陰影中,所有在外部的物體被該光源照亮。
實際的陰影體如下計算:
- 找到所有的輪廓邊(將前向面和後向面隔開的邊)
- 將所有的輪廓邊向遠離光源的方向伸展形成一個四邊形。
- 加入前蓋和後蓋到這些表面上形成一個閉合體(不是必要的,是否採用取決於所採用的實現方法)
用法
編輯當前的研究和實現方法側重於使用硬件的模版緩存(stencil buffer)來優化算法以利用硬件加速 - 參看模版陰影體。
為測試繪製的圖像的給定像素是否在陰影中,陰影體本身需要被繪製,但它是繪製到模板緩存,而不是最終的圖像中。對於每個陰影體中的前向面,模板緩存中的值是增加的;對於後向面,它是減少的。
一旦所有陰影體中的面被繪製到模版緩存,任何值非零的像素將處於陰影中。
要理解其原因,考慮從像素到屏幕的光線反向回到物體的射線 - 若它穿入陰影體,它將會穿過一個前向面,所以模版緩存對應像素的值會增加。若它又穿出陰影體(通過一個後向面)該值將會再次減少。
但是如果該像素在陰影中則該值只在它從後面離開陰影體時被減少,所以該值非零。
圖1顯示了一個包含一個鏡頭,一個光源,一個陰影產生物體(藍色圓圈)和三個陰影接受物體(綠色的方塊),全部用二維示意。粗黑線表示陰影體的輪廓。從相機(笑臉)投射的線表示視線。
該視線首先擊中物體a;在該點它沒有達到陰影體的任何面,所以幀緩存會有0值 - 不在陰影中。在點1陰影體的一個前向面被穿過因而增加了模版緩存中的值。然後我們擊中物體b;在該點我們在緩存中有一個值為1,所以該物體在陰影中。沿着視線繼續前進,我們會在點2到達陰影體的後向面,因而把模版緩存中的值減少到0。最後我們擊中物體c,模版緩存中的值又是0,所以該物體也不在陰影中。
該算法的一個問題在於若相機(眼睛)本身在陰影體中則該方法會失敗 - 視線首先穿過陰影體的後向面,將模版緩存中的值減少1,使得它在到達物體c的時候有非零值,雖然該物體不應該在陰影中。
這個問題的一個解決辦法是從無窮遠的某點返回到相機。該技術由一些人獨立發現,但是由John Carmack推廣,並經常被稱為Carmack的翻轉。
參看
編輯外部連結
編輯- https://web.archive.org/web/20100531060920/http://www.gamedev.net/reference/articles/article1873.asp - 一篇優秀的介紹文章
- http://www.gamedev.net/reference/articles/article2036.asp[失效連結] - 基本算法的另一解釋
- https://web.archive.org/web/20090904173353/http://developer.nvidia.com/object/fast_shadow_volumes.html
- https://web.archive.org/web/20031004133623/http://developer.nvidia.com/object/robust_shadow_volumes.html
- http://www.sgi.com/software/opengl/advanced96/node48.html (頁面存檔備份,存於互聯網檔案館)