《Fundamentals of Computer Grahpics》虎书第三版翻译——第一章 介绍
1.1 圖形領域
在任何領域進行強分類是危險的,但大多數從事圖形學行業的人都會贊同以下這些計算機圖形學的主要領域:
建模:使用數學規格進行建模,這些數據是能存儲在計算機上的形狀和外觀屬性。例如,一個咖啡杯可以被描述作為一組以一些插值規則連接的有序的三維空間上的點,以及反射模型,該模型描述了光與杯子是如何相互作用的
渲染:出自美術的一個專業術語,用于生成從3D計算機模型渲染后的圖像
動畫:通過一系列圖像創造幻覺運動的一門技術。動畫使用模型和渲染但添加了隨時間運動的關鍵問題,在基本的建模和渲染中這類問題并不常見。
還有許多其他領域涉及到計算機圖形學,但他們是否是計算機核心領域因人而異。這些內容在本書內容會至少會提及一點。內容包括:
用戶交互:它處理用戶和輸入設備的接口,例如鼠標和鍵盤,應用程序,將圖像反饋給用戶,以及其他感官的反饋。從歷史上看,這一領域與圖形IC有很大的關聯,因為圖形學研究人員是最早接觸這些無處不在的輸入/輸出設備的。
虛擬現實:嘗試讓用戶沉浸在3D世界。這通常需要立體圖形以及對頭部運動的反應。為了更加逼真的虛擬現實,聲音和力反饋也應該提供。因為這一領域需要先進的3D圖形和先進的顯示技術,所以它通常與圖形密切相關。
可視化:通過可視化讓用戶理解復雜的信息。通常這些圖像與圖形學問題息息相關。
圖像處理:處理2D圖像的操作。被用于圖像和視覺兩個領域。
3D掃描:使用測距技術創建測量的三維模型。這些模型對于創造復雜的視覺圖像很有用,而且處理這些模型需要用到常用的圖形學算法
計算攝影:利用計算機圖形學、計算機技術視覺和圖像處理方法,以實現新的攝影方式,從根本上捕獲對象、場景和環境。
1.2 主要應用
幾乎所有的領域都可以用到計算機圖形學,但是計算機圖形學技術的主要使用者包括以下行業:
電子游戲:對復雜的3D模型和渲染算法的使用日益增長
卡通:通常由3D模型直接渲染而來。許多傳統的2D卡通動畫的使用3D模型渲染出來的背景,這樣可以不斷移動的視點,且不需要花費大量藝術家的時間。
視覺效果:使用了幾乎所有類型的計算機圖形學技術。幾乎每部現代電影都使用數字合成來讓前景和背景疊加。許多電影還使用 3D 建模和動畫來創建合成環境、物體,甚至 大多數觀眾永遠不會懷疑的角色不是真實的。
動畫電影:使用了許多與視覺效果相同的技術效果,但不需要讓圖像看上去很真實。
CAD/CAM :代表計算機輔助設計和計算機輔助制造。 這些領域使用計算機技術在電腦上設計零件和產品,然后使用這些仿真軟件來輔助制造。 比如很多機械零件都是在 3D計算機建模包中設計的,然后在計算機控制的銑削設備上自動生產。
模擬:可以被認為是精密的視頻游戲。 例如,一個飛行模擬器使用復雜的 3D 圖形來模擬開飛機。 這種模擬對于那些安全性十分重視的領域在前期培訓上很有幫助,例如駕駛。以及對培養有經驗的用戶的場景培訓非常有用,比如創造成本高昂或危險的特殊消防場景。
醫學成像:通過掃描患者的數據來創建有意義的圖像。例如,計算機斷層掃描(CT)數據集是由密度值的大型3D矩陣組成的。計算機圖形學用于創建渲染后的圖像,幫助醫生提取出最重要的信息。
信息可視化:不需要形象化描述就能創建數據的圖像。例如,不需要形象化描述就能通過這些巧妙的繪圖技術來描述十種不同股票的價格的變化趨勢,這樣可以幫助人們很容易找出這些數據的規律。
1.3 圖形API
使用圖形庫的關鍵是使用圖形學API。應用程序接口 (API) 是執行一組相關操作的標準函數集合,而圖形API是將圖像和3D表面繪制到屏幕上的基本操作的一組函數。
每個圖形程序都必須能夠使用兩個相關的API:用于視覺輸出的圖形API和用于用戶輸入界面API。當前,圖形和用戶界面API有兩種主要的典型。第一種是集成方法,以Java為例,它的圖形和用戶界面工具包是集成的且可移植的程序包,這些程序包已完全標準化并成為語言的一部分。第二種以Direct3D和OpenGL為代表的,其中繪圖命令是與語言綁定的軟件庫(比如C++)的一部分,并且用戶界面軟件是一個獨立的實體,可能因系統而異。在后一種方法中盡管對于簡單的程序,也許可以使用可移植庫層來封裝系統特定的用戶界面代碼,但是編寫可移植代碼很麻煩。
無論你選擇哪種API,基本的圖形調用都基本相同,本書的概念也都適用。
1.4 圖形管線
如今,每臺臺式電腦都有一個強大的3d圖形管道。他是一個特殊的軟/硬件子系統,可以有效的繪制基本的3D物體的透視圖。通常這些系統可以優化那些具有共享頂點的三維三角形。管線的基本操作是將3D頂點位置映射到2D屏幕位置并對三角形進行渲染,使他們看上去很逼真,并以適當的前后順序顯示。
盡管以有效地以從后往前的順序繪制三角形在當時是最重要的研究問題,但是現在總能使用Z緩沖區解決,它使用了一個特殊的內存緩沖區來以蠻力解決這個問題。
事實證明在圖形管線所使用的幾何操作幾乎能在由三個傳統的幾何坐標和輔助透視用的第四個齊次坐標組成的思維空間坐標完成。這些4D坐標是使用4×4矩陣和4維向量處理的。因此,圖形流水線包含了許多機器,以便有效地處理和組成各種各樣的矩陣和向量。四維坐標系是計算機科學中使用的最微妙和美麗的結構之一,這無疑是學習計算機圖形學時需要翻過的最大的障礙。每本圖形學書的第一部分的絕大部分都在與這些坐標打交道。
圖像生成的速度很大程度取決于繪制三角形的數量。由于交互性在很多應用程序比視覺質量更重要,因此很有必要讓表示一個模型所使用到的三角形數量盡可能的最小。此外,如果模型離視野很遠的話,需要三角形的數量應該比離視野近的要少。這表面以多細節層次處理(LOD level of detail )表示三角形是很有用的。
1.5 數值問題
許多圖形學程序實際上只是3D數學代碼。對這類程序來說數學問題通常是至關重要的。在“舊時代”,很難以健壯和可移植的方式處理這些問題,因為機器在內部數字表示不同,更糟糕的是以不同和不兼容的方式處理異常。幸運的是,幾乎所有的現代計算機都符合IEEE浮點標準(IEEE標準協會,1985)。
這方便了程序員對如何處理某些特定數值作出判斷。
盡管IEEE 浮點有很多特性在編碼數字算法時非常好用,但對于圖形中遇到的大多數情況,只有少數幾個特性是關鍵的。首先,也是最重要的,是要理解在IEEE 浮點中有三個實數的“特殊”值:
IEEE浮點有兩種表示形式的零,正零和負零。 雖然?0和+0之間的區別偶爾很重要,但是當他發生的時候最好牢記它。
IEEE浮點標準的設計師做出的一些設計對于程序員來說非常方便。在處理除0異常的時候,許多處理方式于前面三個特殊值有密切關系。在這些情況下,異常會被計算機記錄下來,但在許多情況下,程序員可以忽略該異常。具體來說,對于任何正實數a,涉及無窮大除法的規則是這樣的:
+a/(+∞) = +0
?a/(+∞) = ?0
+a/(?∞) = ?0
?a/(?∞) = +0
涉及無窮的運算法則和人們預想的一樣,對于正數a,例如:
∞+∞= +∞
∞ ? ∞=NaN
∞ × ∞=∞
∞/∞=NaN
∞/a =∞
∞/0 =∞
0/0 = NaN
包含無窮值的布爾表達式中的規則如下所示:
涉及具有NaN值的表達式的規則很簡單:
IEEE浮點數最有用的方面可能是如何處理零除;對于任意正實數a,除以零的規則是這樣的:
+a/+0 = +∞
?a/+0 = ?∞
如果程序員利用IEEE規則,許多數值計算就會變得簡單得多。例如,考慮這個表達式:
這樣的表達會出現在電阻和透鏡情形中。如果除以零將導致程序崩潰(在IEEE浮點數出現之前,許多系統中都會這樣),則將需要兩個if語句來檢查b和c是否為很小的值或零值。而現在有了IEEE浮點數,如果b或c為零,我們則將根據需要將a賦值為零。避免特殊情況檢查的另一種常用技術是利用NaN的布爾屬性。考慮以下代碼段:
A=f(x)
If(A>0)then
Do something
在這里,函數f可能會返回很不想看到的值,例如∞或NaN,但是if語句的條件是明確的:a = NaN或a =-∞時為false(a < 0),而a = +∞時為true(a > 0)。在確定返回什么值時,if語句通常可以做出正確的選擇,無需進行特殊檢查。這使程序更小,更可靠和更高效。
1.6 效率
沒有使代碼高效運行的魔法。效率是通過仔細權衡來實現的,對于不同的架構這些權衡是不同的。但是在不久的將來,一個很好的啟發是程序員應該更多注重內存訪問模式而不是操作次數。這與20年前最好的啟發相反。之所以會發生這樣的變化是因為內存的速度已經跟不上處理器的速度了。由于這種趨勢一直持續著,有限且一致的內存訪問對于性能優化的重要性只增不減。
加快代碼速度的合理方法是根據需求按以下步驟順序進行:
這些步驟最重要的一步是第一步。大多數優化只會讓代碼可讀性更差而且優化了個寂寞。而且,把時間花在優化上還不如去修bug或者加功能。另外,要小心舊教材;一些經典技巧,例如把實數換成整數,可能不再提高速度,因為現代CPU執行浮點運算的速度跟整數運算一樣快。在任何情況,我們應該對機器和編譯器盡可能的優化。
1.7 設計和編寫圖形程序
某些通用的方法在圖形學程序很有用。在這一節中。我們提供了一些對你學習本書有所幫助的建議。
1.7.1 類設計
任何圖形學的關鍵部分在于為幾何實體(矩陣和向量)以及圖形實體(RGB三原色和圖片)提供良好的類或者示例。這些示例應該盡可能的有效和簡潔。一個常見的設計問題是我們是否需要把位置和位移歸為不同的類,因為他們的運算規則是不一樣的。位置1/2沒有任何幾何意義,但位移1/2是有的。在這個問題上幾乎是沒有共識的,這可能會引發圖形學從業者進行數小時激烈的爭論。但為了舉例,我們假設不會對它們做出分類。
這意味著我們要編寫一些基類,包括:
Vecrtor2:存儲x和y分量的2D向量類。他應該將這些組件存儲在長度為2的數組中以便能很好的支持索引操作。你也應該包含向量加法,向量減法,點乘,叉乘,標量乘法,和標量除法等運算
Vecrtor3:類似于Vector2
hvector:具有四個分量的同質向量(齊次)
Rgb:存儲三個分量的RGB顏色。你也應該支持RGB加法,RGB減法,RGB乘法,標量乘法和標量除法的運算。
Transform:用于變換4*4的矩陣。你應該包含矩陣乘法和成員函數,應用于位置,方向,表面法向量。這些都是不同的,在第六章會看到。
Image:就具有輸出操作的二維rgb像素數組
您可能還想到了用于單位矢量的特殊類,盡管它們很讓人痛苦
您可能還想到了用于單位矢量的特殊類,盡管它們很讓人痛苦
1.7.2 Float vs Double
現在體系結構表面,降低內存使用和保持內存訪問一致是提高效率的關鍵。著以為使用單精度數據。然而,避免數值問題建議使用雙精度算法。權衡屈居于程序,但最好在類中使用有一個默認值。
我建議使用double進行幾何計算和顏色計算。對于占用大量內存的數據(例如三角形網格),我建議使用float存儲,但是用成員函數訪問數據時轉換為雙精度。
1.7.3 調試圖形程序
如果你四處詢問,你可能會發現,隨著程序員越來越有經驗,他們使用傳統調試器的次數越來越少了。使用這樣的調試器對復雜的程序比簡單的程序要復雜的多。另一個原因是最難調試的是概念錯誤,即執行了錯誤的內容,并且很容易調試了半天缺還找到bug出現的地方。我們發現一些調試方法在圖形方面特別有用。
科學的方法:在圖形程序中,有一種很有用的替代傳統調試的方法。它的缺點是,它與計算機程序員在職業生涯早期被教導不要做的事非常相似。所以,如果你這樣做,你可能會覺得很”調皮”:我們創造一個圖像,并觀察他有什么問題,然后我們對出錯原因進行假設并測試它。例如,在光線追蹤程序中,我們可能會有許多看起來暗像素。這是大多數人在寫光線追蹤時遇到的典型的”陰影痤瘡“問題。傳統的調試在這里沒有幫助。相反,我們必須認識到,陰影射線擊中的是正在著色的表面。我們可能注意到,黑點的顏色是周圍環境的顏色,所以,缺少直射光。直射光可以在陰影中關閉,所以你可以會假設這些點被錯誤的標記為陰影,但他們不是。為了測試這個假設,我們可以關閉陰影檢查,并重新編譯。這表面這些是錯誤的陰影測試,我們可以繼續檢查。這種方法有時候是良好的實踐,因為我們不必發現錯誤的值或真正確定概念錯誤。相反,我們只是通過試驗縮小了我們的概念誤差。通常只需要進行幾次試驗就可以找到問題所在,并且這種調試很有意思。
調試代碼輸出的圖像:在許多情況下,從圖形程序中獲取調試信息的最簡單方式是輸出圖形本身。如果你想知道計算每個像素所用到的某個變量的值,你可以臨時修改你的程序的值,并將這些值直接復制到輸出圖像并跳過其他的計算。例如,如果你認為是法平面導致渲染問題,你可以直接將法向量直接復制到圖像(x軸變為紅色,y軸變為綠色,z軸變為紅色),這些色碼圖解就是你程序中實際向量。或許,你懷疑某個特定值有時會超出有效值的范圍,你可以讓你程序在發生這種情況的時候繪制出高紅亮色的像素。其他常見的技巧包括用明顯的顏色繪制表面的背面(背面是看不到的),根據物體的ID號給圖像上色,或者根據計算的工作量給像素上色。
使用調試器:仍然有一些實例,特別是當科學發展遇到了矛盾的時候,當沒有什么能代替現在正在發生的事情的時候。問題在于,圖形程序經常涉及到對相同代碼的多次執行(每個像素執行一次,或者每個三角執行一次),這使得從頭開始調試逐步調試變得不切實際。最難解決的bug通常只發生在復雜的輸入。
一種有用的方法是為bug“設置陷阱”。首先,確保您的程序是確定性的——在單線程中運行它,并確保所有隨機數都是從固定種子中計算出來的。然后,找出哪個像素或三角形出現了bug,并在您覺得寫錯的代碼前面添加一條語句,該語句僅在可疑情況下才會執行。例如,如果您發現像素(126,247)出現錯誤,就添加:
if x=126 and y=247 then
Pirnt “blarg!”
如果你在打印的句子中設置了斷點,你可以在計算您感興趣的像素之前進入調試器。一些調試器具有“條件斷點”功能,可以在不修改代碼的情況下達到相同的效果。
在程序崩潰的情況下,傳統的調試器對于查明崩潰的位置很有用。然后,您應該使用斷點和重新編譯在程序中開始回溯,以查找程序出了問題的地方。這些斷言應留在程序中,以備將來可能添加的錯誤。這再次意味著避免了傳統的逐步過程,因為那樣就不會在程序中添加有價值的斷言。
數據可視化以進行調試:一般來說,很難理解你的程序在做什么,因為它會在最終出錯之前會計算出許多中間結果。這種情況類似于測量大量數據的科學實驗,它們的解決方案是相同的:為自己做好設計方案和圖解,以了解數據的含義。例如,在光線跟蹤中,你可能會編寫代碼以可視化光線樹,以便可以看到對像素有作用的路徑,或者在圖像重采樣例程中,你可能繪圖,來顯示從輸入中采樣的所有點。為可視化程序的內部狀態所花費的時間,會得到回報,因為在優化時,能夠更好地理解程序的行為。
總結
以上是生活随笔為你收集整理的《Fundamentals of Computer Grahpics》虎书第三版翻译——第一章 介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开心一刻:今天下班后,我尾随一女同事,为
- 下一篇: 这只“鸭子不一般”科大讯飞申请“躺倒鸭”