DDA, Bresenham line's algorithm and Voxel Traversal used in the Grid-Accelerator in PBRT

 
 
- DDA(Digital Differential Analyzer, 數值微分法) - 
 
計算機圖形學中,常常會遇到一些計算機中」經典「的問題。例如,如何利用計算機」離散「的特質,模擬現實中」連續「的概念?關於這個問題的一個具體應用,就是如何利用計算機」畫直線「的問題。咱們知道在純粹抽象的數學中,一條直線用y=mx+b就能夠表達(其中m是斜率);但若是要畫在計算機屏幕上,就沒那麼容易:由於計算機屏幕是由許多分散的像素格子組成的,你須要決定在何時換行或者換列。這種模擬的本質,仍是」插值「問題。直線是最簡單的狀況,往復雜點說,就會有考慮如何插值三角形甚至多邊形的狀況。不過它們都是」直線「插值的複雜應用,下面就很少說了。
 
DDA是一種處理此種問題的經典算法。算法思想倒也不難:
 
準備階段
 
1) 給定一條線段的起點(x1, y1)和終點(x2, y2),分別計算在兩軸上的差值 △y = y2 - y1 和 △x = x1 - x2。
 
2) 比較△y和△x兩者誰比較大,大的那一個就做爲遍歷的總步數。steps = max(△x, △y)。
 
3) 分別計算在x和y方向上單步的步距。 dx = △x/steps,dy = △y/steps。注意此時dx和dy必然一個等於1,一個介於0-1之間(浮點數)

 

【遍歷階段git

4)△x和△y誰大,誰就做爲插值的主序方向。意味着每次插值都是朝這個方向行進一步。好比△x大,那麼假設當前在格子(xi, yi)處,決定下一個格子時,因爲在x方向是主序方向,因此朝x方向行進一步獲得xi+1。剩下的就是決定y方向上究竟是yi呢仍是yi+1呢。
web

 

5)究竟是yi仍是yi+1,要看根據y = m(xi+1) + b計算出真實的y等於多少。這時的y計算出來的是浮點數,根據float2Int的一些規則,轉換成對應的整形而後找到對應的格子。float2Int的轉換規則要看具體狀況,四捨五入仍是直接截取,看效果吧。算法

 

6)重複4)-5)步架構

 

DDA算法直接了當,簡單易懂。不過它的計算過程當中涉及到許多浮點數運算,這在當今的CPU設計架構中運算成本較大,也可視爲其運算複雜度較高。下面的Bresenham line's algorithm就是對其的一種改進。測試

 

 

- Bresenham line's algorithm - spa

Bresenham line's algorithm 是DDA的一種改進算法。它與DDA相比有質量和效率的兩點改進:設計

1)質量方面的改進。 好比仍是以△x爲主序方向行進時,決定下一個點是落在yi仍是yi+1,不只僅考慮真實計算出來的y等於多少,還要考慮這個y值是離yi更近仍是離yi+1更近。誰近就畫在誰的格子裏。這一點顯然比DDA中思考問題的方式更加make sense。

orm

2)效率方面的改進。根據上一點的判斷準則,再加上一系列的遞歸推導,最後簡化到只存在整形的加減運算以及比較操做。這在當今CPU的架構中運算成本相對來講很是便宜,所以效率更高。具體的推導細節,參見這篇 DERIVATION OF THE BRESENHAM’S LINE ALGORITHM遞歸

 

  

- Voxel Traversal used in the Grid-Accelerator in PBRT -ci

我正在看pbrt的第4章。這章主要講了有關場景管理組織的一些技術,目的是爲了提升射線相交測試(ray intersection tests)的效率。主要的手段有三種,Grid-Based, BVH  KD-Tree。目前正看到第一種,Grid-Based,基於網格的場景管理技術 

基於網格的場景管理方法,至關於把整個場景看做是一個大的bouding box,而後對這個box所在的空間分別在三個維度上劃分紅一格一格的。而後將場景中的primitives與各個發生overlap的格子」關聯「起來。接着,從射線的方位出發,遍歷(traverse)這個網格系統,對於與射線發生相交的格子,再在裏面遍歷與之關聯的全部primitives,對遍歷到的每一個primitive都作一次相交測試。固然這當中的細節還有不少,就不贅述了。總之這種算法的思想能夠描述爲」分而治之「。經過每一個格子的空間管理與之有關的primitives,測試某個格子的時候就沒必要考慮其餘格子裏的primitives,從而能夠有效降解其遍歷場景的複雜度。

這裏,我想強調下射線是如何遍歷這個網格系統的。其方法也是DDA算法的一種改進,書中說很是像Bresenham line's algorithm。但我仔細觀察了一下,和Bresenham的算法仍是不同的。這裏的關鍵是利用的是射線的參數(parametric)方程,那個參數t(做爲沿着射線方向偏離起點的距離)是很重要的。當決定下一點到底是朝x方向,y方向仍是z方向步進時,要看這條射線」最早打到哪一個方向的下一格子的邊界「。哪一個方向的邊界先被打到,就朝哪一個方向步進一次。這樣一來,這種算法就不是依靠決定」哪一個方向是主序「的思路進行的了,每次判斷步進時三個方向皆有可能步進。這點與經典的DDA(包括Bresenham)算法都很是不一樣。

我知道我沒說清楚,剛纔在網上粗略找了找,發現這篇應該纔是pbrt中使用的算法:A Fast Voxel Traversal Algorithm for Ray Tracing。(我沒細看,大致以爲差不了)。歡迎指正校對勘誤拍磚頭,謝謝。

相關文章
相關標籤/搜索