【讀書筆記】計算機圖形學基礎(虎書)第1章 - 介紹


思維導圖

第一章 - 介紹

1. 計算機圖形學的主要研究領域

最重要的是以下三個

  • 建模(骨),以數學方法,利用點線連接與反射模型等對物理世界物體進行建模,並編寫與周圍物件的交互方式
  • 渲染(皮肉),為3D模型添加光影、材質、環境等
  • 動畫(動作),利用一連串的圖片偽造持續運動的錯覺,時間(例如關鍵幀的處理)為重要的因素。

其他也包括用戶交互虛擬現實(VR)(各類)可視化圖片處理(PS等修圖)、3D掃描攝影(拍照濾鏡)

2. 計算機圖形學的主要應用領域

-電子游戲,例如光照,實時渲染,紋路等
-卡通動畫,例如3渲2、3D動畫等
-電影特效,例如綠幕后期,存在帶動電影界改革的現象
-CAD/CAM,Computer Aided Design/Manufacturing,例如工程/建築建模、3D打印建模以及最近的VR繪畫/建模等
-模擬,例如飛行模擬器、賽車模擬器等
-醫學成像,各類掃描技術,已經逐漸可以獲得帶顏色的3D圖來尋找病灶
-數據可視化,尋找特殊的繪圖方式給較為雜亂的數據歸納總結

3. 圖形API

平台介紹

為了更好的跨平台與GPU和其他硬件進行溝通,一些高級抽象的圖形學API被發明出來,主要分為以下兩種。

  • UI與圖形結合,例如Java為基礎的圖形學API,利用各平台通用的package來開發
  • 僅編寫圖形,例如Direct3DD和OpenGL,需要額外設計UI。常見的例如C++后台的OpenGL+設計UI的Qt

后一種API可移植性較低,需要通過其他的方法來處理多平台的問題,例如檢測運行環境再使用不同的程序。

回調函數(callback function)

在與前端UI進行交互時,往往使用callback(回調)的方法。(英文解釋中文解釋)。具體來講,區別於常見的修改A函數並在函數內調用B函數,我們選擇將B函數放在A函數的參數內(指針引用等方法)。通過這種方法即使A函數被封裝好,我們也可以通過修改A函數的參數來實現不同的目的。例如當前端UI的按鈕被點擊時,觸發一個button_Pressed(void (*callback)(void))的函數,我們可以選擇不同的callback函數放到button_Pressed()的參數內,例如exit_game()和start_game(),這樣同類的兩個button可以觸發兩個不同的事件。

4. 三維模型

在圖形學中,最常見的三維模型是以若干個三角形組成、共享頂點、全封閉的三角網格(3D mesh)。具體的數據結構差距較大,個人使用過的是半邊結構(half-edge)。

5. 圖形管線(Pipeline)

此部分具體見后面的章節,總體來講,圖形管線的設計目的是以分層的方法來增加繪圖的效率與可理解性,現在的圖形管線主要優化三維三角形與共享頂點的繪制。對於初學者來講,一種粗略的理解是從內存提取頂點信息->按某種規則處理頂點信息->三角形化頂點(獲得邊等信息)->光柵化(根據邊等信息尋找哪些像素應該被繪制)->決定每個像素應該被怎么畫->把像素畫到屏幕上)
如果你有一些英語基礎並希望在此階段對圖形管線有所了解,請點擊此鏈接
管線示意圖
圖形管線中每一步都有值得分析的操作,其中最重要的一步即在坐標系中采取4x4的矩陣,前三列代表xyz位置,而最后一列使用齊次坐標(homogenous coordinate)的技巧,主要服務於 3D空間內的坐標變換,這樣坐標變換就可以輕松的用連續的矩陣相乘來表示(而不是一些加一些乘)。 又例如在光柵化的時候我們要決定哪一個物體更靠近攝像機並被繪制,在此會運用到一個z-buffer的技巧,即將物體到攝像機的距離算作z向量,記錄每一個像素點內最近的z向量與對應的圖形,加以繪制,過程比較像圖論單元最短路問題中更新距離矩陣。

就繪制效率而言,圖形管線的速度基本與需繪制的三角形數量成正比。因此,減少需繪制的三角形就成為了一個優化速度的好方法。當繪制較遠距離的場景時,經常會通過降低三角形的數量來優化速度,引申出了多層次細節(level of detail)這個概念。另一個例子是只繪畫在攝像機前且未被遮擋的物體,這個技巧叫做面剔除(face-culling)

6. 數值問題(特指數值在計算機內的表達方式問題)

在圖形學內因為操控的大部分都是小數,因此數值的精度十分重要。在計算機發展的早期年代,不同硬件采取不同的數值標准,為可移植性帶來巨大的困擾。現在在絕大部分地方通用的IEEE浮點標准為我們免去很多煩惱,但是仍需維持對於浮點數精度問題的認識和注意。一個例子是在之前Z-buffer的例子中,如果Z值極其類似,例如1.00與0.9999999,可能會存在誤判導致圖形的重疊交錯效果,具體圖片可見此文章

在IEEE的特殊值中,我們需要注意正無限,負無限,正0,負0與NaN值(undefined)。
除了直覺上正確的大小無限與實數關系外,總結邏輯為

  1. 無限作為被除數或\(0/0\)時結果為NaN
  2. 無限相減結果為NaN(無限之間不分大小)
  3. 含NaN的代數操作結果一定為NaN
  4. 含NaN的邏輯操作結果一定為NaN
  5. 除了\(0/0\)以外,被除數為0時結果為無限
  6. 結果的符號取決於前兩個元素的符號,例如 \(+a/(-\infty)=+0\)
    需注意對於邏輯運算符轉換來講,正無限被視作TRUE,負無限與NaN被視作FALSE。

7. 代碼效率(Efficiency)

因為現代CPU與多核的研發,代碼效率分析的重心慢慢從操作的數量(Operation Count,我們常說的時間復雜度)轉移到內存訪問模式(傾向於空間復雜度,但着重於內存放的位置、調用方法、cache、雲空間等)。

本書推薦的方法是

  1. 以最快的方式把代碼寫出來
  2. 以優化模式(optimized mode)去編譯代碼
  3. 用分析工具發現瓶頸問題
  4. 檢查數據結構來直接改進,盡量讓數據大小與機器cache/page的大小一致,減少分割數據的時間
  5. 檢查編譯器代碼是否缺乏效率,重寫源代碼解決問題。

使用第一步的主要目的是為了將預先優化代碼的時間用於糾正錯誤和添加新的特性,並且很多預先優化並沒有起到作用,反而使代碼變的復雜和難以閱讀。與此同時,開發者需要對現存技術有所了解,例如CPU的進化使其處理整數和浮點數差不多快、編譯器的一些自我優化等,這樣能避免一些無意義的優化。

8 圖形程序的設計與編程

常用的類(Class)

通常使用234維向量代表點位置、4x4矩陣代表變換方式、3色RGB(代表像素顏色)和圖片的數據格式。另外常用四元數(quarternion)來代表方向(主要理解代數),此階段略看即可。

單精度vs雙精度浮點(float vs double)

原則上選擇一個來用,具體哪一個視開發情況而定。普遍來講double的精度更大,可保持數值操作更穩定且更貼近於真實數學。float占據空間較小,操作更快。

調試圖形程序

  • 科學方法
    像科學家一樣,生成一個圖像看有什么問題,提出一個假想或猜測、測試然后修改問題。這種方法需要對底層知識有所了解,有相對豐富的經驗去猜測問題可能發生的原因,並不適合新手。好處是可以快速的縮小概念錯誤的可能范圍。
  • 利用圖像作為調試輸出
    通過輸出圖像來進行調試,例如在猜測曲面的法線是不是寫錯了的時候,可以屏蔽其他圖,把法線轉換成一條帶顏色的單位向量並進行觀察來調試,如果全部線垂直往外為正確,否則錯誤。其他例子包括繪制溫感圖查看檢測人物移動時皮膚變形錯誤是不是因為骨骼頂點影響系數寫錯了,如果溫感圖確實越靠外溫度越低,那么才是正確。
  • 調試技巧
    因為通常會遍歷很多點和三角形,我們需要特殊的方法來進行調試。例如如果我們發現(5,5)這個像素點有問題,我們就額外編寫代碼並跳轉至此,而不是連續點擊step next至(5,5)。同時打印信息在里面找異常處、如其他程序一樣在必要時拋出異常等也是很好的方法。
  • 調試的數據可視化
    將中間結果放入R、matlab、excel或python之類的數據可視化地點,分析數據的含義,查看是否符合期望。此部分與圖像調試輸出類似。例如光線追蹤器中可視化光線樹。(個人對此的感悟並不深,需要以后添加其他例子)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM