【電腦圖學】00-OpenGL

帽捲
Maochinn
Published in
13 min readJul 9, 2020

首先,什麼是電腦圖學?從廣義上來說,就是由電腦產生圖形到畫面的過程所牽涉到的所有領域,但如果要比較限縮範圍的舉例:玩具總動員就是第一部完全利用CG製作的動畫長片,那你大致會有一個概念,電腦圖學可以產生像是玩具總動員那類的3D模型的動畫。

引言

那麼我們大概理解甚麼是電腦圖學之後,回到現實面,為甚麼大多數的CG的課程都會要學習OpenGL呢?這篇文章的目的是做一些電腦圖學的概論,並且一路連結到OpenGL。

先說結論,OpenGL就是一個專門處理圖形的函式庫,因此,OpenGL就是一種電腦圖學Rendering的實現,反過來說,電腦圖學也有其他的實現方式,因此也會有其他的圖形函式庫存在,但是,在教學上,我們常用OpenGL的實作來理解電腦圖學的理論

目錄

3D Computer Graphics
Graphics Pipeline
OpenGL
GPU

3D Computer Graphics

電腦圖學(Computer Graphics, CG),雖然簡稱是CG,但這邊也不是指電繪或者是數位繪圖(Digital Painting)(我絕對不是因為誤會而去修這門課的),其中,比較狹義的理解CG通常就是針對三維的CG,如wiki所描述,3D computer graphics production workflow falls into three basic phases:

  1. 3D modeling — the process of forming a computer model of an object’s shape
  2. Layout and CGI animation — the placement and movement of objects (models, lights etc.) within a scene
  3. 3D rendering — the computer calculations that, based on light placement, surface types, and other qualities, generate (rasterize the scene into) an image

簡單來說,就以3D動畫為例,其構成類似於拍攝現場,場景中會需要模型、燈光、攝影機等,但是在電腦中場景中的所有元素都是虛擬數位化的,因此模型需要建模(modeling)才可以得到,模型與燈光需要布置(Layout)在虛擬的場景中,攝影機「拍攝」場景的過程則是算繪(Rendering)。

3D Modeling

我們可以理解成「產生出3D模型的過程」,例如:人工建模程序化建模(Procedure Modeling)以及重建(Reconstruction)等,除了模型的幾何資訊之外也包含貼圖(texture)、材質(Material)之類的資訊,總之就是把模型在三維空間中定義出來,對應的軟體像是Maya, Solidworks等。

另外,模型的表示形式也會影響如何modeling,例如:我們用人工拉出來的模型通常是網格(mesh),用照片重建出來的模型則常會是所謂的點雲(point cloud)。無論是如何建模或是模型本身都有細分很多領域,每個領域也都是個大哉問。

建完模之後就會得到3D模型網格(mesh),就要把這些物件、攝影機放在場景之中,或者是加入時間因素,也就是某個時間某個物件要放在場景的哪裡,事實上,這就是動畫。

Layout and CGI animation

跟modeling類似,這個領域也是有分人工做的、程式生成的現實重建的,前者可能是人依照自己的經驗,用傳統2D動畫的知識去拉關鍵幀,中者則可能是有了關鍵幀後用電腦去內插補幀,可能是在3D補也可能像現在用AI在2D補,後者透過動作捕捉來從現實中重建動畫。

通常來說,三者會混合使用,因為我們總希望從現實演員得到動畫,並且能夠人為干涉,並且給定關鍵幀直接用程式計算中間的動作,總之,每個領域也都有許多技術。

那麼在一切都Layout完成之後我們就要利用攝影機「拍攝」場景,或者是說將場景中資訊「繪畫」到螢幕上,這就是Rendering

3D Rendering

Rendering可能會翻譯成渲染、算繪、彩現,根據定義上算繪是比較好的翻譯,但大部分文章跟口語的習慣上會翻成渲染。

概念上來說,我們會在將在虛擬場景中的3D模型,設定好的光源、相機等各種物件,將模型「繪畫」到畫面上,最重要的是,無論在Modeling的過程當中或是調整Layout的過程中其實都會需要用到Rendering,因為人通常會在一個圖形化的介面中調整物件,也就是在調整的過程當中都需要顯示到畫面上。

因此,無論是哪個細分領域,Rendering是絕對需要的部分,而且也會簡單的碰觸到所謂的模型、燈光、布局等基本概念,因此,在教學上都會先講述Rendering的概念,而在實作上Rendering其實就是一個流水線,我們會稱之為Rendering Pipeline或是Graphics pipeline

Graphics Pipeline

根據wiki在整個流水線中我們大致可以分成三個部分Application、Geometry、Rasterization,簡單來說就是透過這三個步驟將場景render到畫面上。

A graphics pipeline can be divided into three main parts: Application, Geometry and Rasterization

Application

簡單來說就將前面提到的布局後的結果,因為不一定所有的布局都是off-line設定好的,可能會有部分的資訊是run-time產生的,換言之,每一幀的資訊可能會動態產生變化,例如:物理計算(也就是物理引擎)。

若從執行的單位來看,這部分的計算大多數是在CPU,等將所有場景資訊更新完後就會將資料傳入GPU,進入下一個階段。(為甚麼要傳入GPU後面會解釋)。

Geometry

簡單來說,就是將場景中的模型、燈光等依據Application給的空間資訊,應用在模型、燈光上,因為這個步驟通常做的都是空間上的位移、旋轉、縮放,也就是做幾何(Geometry)上的轉換(Transformation)。

在流程上其實就是把上一個步驟從CPU來的資訊在GPU中進一步計算,在所有三維的transformation都結束後,要將結果畫到畫面上,也就是要將就要將三維的資訊轉換到二維的平面上,也就是Rasterization(光柵化)。

Rasterization

概念上來說,你可以想像我們要將三維的模型「壓扁」成二維的平面,或者我們可以說,將三維的物體投影(Project)到二維的畫面上,那在電腦中,我們要把場景中連續、精準的點、線、面用相對離散的像素表示,因為最終我們都需要顯示成pixel-based的圖片,換言之,這個步驟就是將浮點數資訊轉換到整數的2D array。

那麼在實作上又是怎麼回事呢?因為兩個步驟做的事情一定程度上都是固定的,因此為了避免重複寫類似的程式碼,就會有不同的函式庫來實作這些流程,那其中一個函式庫就是OpenGL。

OpenGL

OpenGL(英語:Open Graphics Library,譯名:開放圖形庫或者「開放式圖形庫」),總之就是一個函式庫,也有很多以此衍伸的函式庫,而針對GeometryRasterization的部分在OpenGL對應的就是Vertex pipelineFragment pipeline。

以上圖來舉例,模型通常由一系列的頂點(Vertex)所組成,並且把她連成三角形,當然這個三角形都是使用者自己決定怎麼連,這個步驟我們可以稱做Vertex pipeline,這個步驟多半也會伴隨很多幾何(Geometry)的變換。之後的Fragment pipeline會將三角形用fragment表示以及計算每個fragment的顏色,這是因為現在大部分的圖片儲存和螢幕顯示都是用pixel來表示,因此這個步驟會包含Rasterization。

補充一下,在不正式的情況下,rasterization中的rasterpixel是差不多的,而fragment也與pixel差不多意思,不同主要是詞的來源不同,這個解釋會牽涉到其他專有名詞,為了不失焦這邊就不解釋,歡迎後續補充。

從上面的流程可以發現,有一些的名詞不知道是什麼意思,例如Vertex shader、Fragment shader、Testing以及Blending,但是可以發現整個流程都是固定的,差別是一開始輸入的Vertex以及uniform state有差,Vertex可以理解就是模型,那uniform state是什麼呢?

簡單來說,以上圖舉例,我們可以設定這個三角形的顏色要由黃綠紅所組成,因此我們可以傳顏色的資訊進入某個步驟中,事實上,OpenGL有大量常數用來設定每個步驟所需的參數,因此,你也可以想像這是一台龐大的狀態機(State Machine),而你只需要透過OpenGL的API設定想要的參數即可,換言之就是設定一些固定的狀態(uniform state)

因此,使用OpenGL的函式多半跟一般函式庫的函式不同,並非是呼叫CPU做某件事,而是在一個已經建構好的圖形管線(Graphic pipeline)中更改參數,或者說設定狀態(State),好處是,這變得相當容易,你不需要自己建構流程,你只需要依照給定的規則設定即可,壞處是,因為流程固定,因此較無彈性以及優化空間,我們會稱之為Fixed Function Pipeline

與之相對的則是可程式化流程(Programmable Pipeline),也就是將部分流程中的步驟開放給程式員自己寫,例如流程中看到的Vertex shaderFragment shader,因此現代的OpenGL會長這個樣子。

重點是中間仍然有一個固定的流程,只是被細分成更多,而能夠從外部設定的參數也變得更多,換言之,隨著彈性變大,OpenGL也變得更複雜,但其核心依舊不變,因此,通常從教學的角度,通常會從所謂的OpenGL1.x開始教,因為你只需要懂一部份的東西就可以render出東西在畫面上。

因此,Rendering通常需要一個由Vertex定義的模型,那麼通常這樣的模型會是一個三角網格,經過上述的流水線畫到顯示裝置,其中會經過無數的轉換(Transformation),包含在幾何空間上的轉換以及色彩的轉換,而這些轉換通常會在顯示卡中運行。

3D Mesh

那至於為甚麼要畫三角形?這有歷史的因素,也有點像雞生蛋,蛋生雞的問題,因為現在看見的3D模型大多數都是由無數的三角面所構成,所以我們會以此為單位render,反過來說,也是因為rendering流程設計成以三角形為單位,所以模型才以此為單位定義,總之,只要會畫三角面,就可以畫出所有種類的東西。

而在Rendering的過程中我們已經知道會要進行一些Transformation,或者說要進行大量的計算,因此,我們就來談談GPU。

GPU

首先,前面有提到,電腦顯現出任何圖形都是經過一連串的計算簡單來說,就是將一堆Vertex的資訊經過一連串的計算最後顯示到螢幕上,這樣的過程在過去是使用CPU來運算,可以想像,CPU需要逐個計算每個像素的顏色。另一方面,GPU的作法則是一口氣計算所有像素的顏色。

如上的影片所呈現的,對於rendering來說GPU明顯是更適合的解決方案,因為在整個pipeline原則上是以vertex或是pixel為單位下去跑的,每個vertex或是pixel彼此獨立互不影響,但所經過的計算的步驟是一樣的,所以我們可以把每個pixel丟下去進行平行運算。因此我大學的指導教授常常這樣跟我講

「大量簡單的運算可以打敗單一複雜的運算,屢試不爽」

這算是CG中的一個主流的發展方向,因為GPU帶來的加速是非常顯著的,在圖學中,我們會稱用GPU計算為Hardware acceleration(硬體加速)

這邊補充說明一下GPU好了,GPU是顯示卡中負責運算的單位,其中有大量的ALU(運算單元),你可以想像成每個ALU會負責計算一個像素的顏色,而事實上,如果你把計算的過程寫成程式碼,你就會發現它是一連串的矩陣運算,因此,你也會發現為甚麼CG領域會用到很多4x4的矩陣或是4x1的向量,因為ALU最多就是支援的4x4的矩陣運算,包含許多的Transformation

總而言之,GPU的架構很適合拿來做大量平行簡單的運算,但你也可以說,當初就是發現rendering有這樣的特性,所以才開發出GPU。

歡迎斗內鼓勵我繼續寫相關文章!

--

--