• 沒有找到結果。

第三章 系統實作

第二節 API 整合和擷取

本節將會介紹如何把OpenGL 3.0 版本固定功能以及矩陣功能整合至 OpenCL

語言撰寫的光線追蹤,看下圖 4 :傳統光柵化管線步驟。

首先在Matrix Transform 時處於 3D 空間座標的物件會轉換到螢幕坐標系上,

這個轉換階段用到的矩陣是投影(projection)矩陣、視覺(view)矩陣和模型(model)

矩陣的乘積(有固定的運算順序),再來 Lighting 階段會計算 Diffuse、Ambient 和

Specular…等標準光照公式,最後才開始執行光柵化相關作業。

大致敘述了傳統光柵化管線後,可以發現上述點名的步驟共通點都是應用使

用者設定的數值來計算,既然這些數值是由人所決定而不是限定光柵化才有用,

那麼就可以直接擷取數據並由整合系統內的光線追蹤來利用。

以下將會分段來介紹如何完成 API 擷取,而這些工作與光線追蹤 host 端前置

息息相關,並為了轉換成kernel 端設計的格式做準備。

圖 4 :傳統光柵化管線步驟

Geometry Matrix

Transform Clipping

Lighting Perspective division

Rasterize Scanlines

15

The matrix manipulation functions

Legacy OpenGL 提供了矩陣系統用來設定光柵化階段所需要的座標轉換,有

Projection 和 ModelView 兩種型態,後者因為視覺矩陣和模型矩陣可以反向操作

來達成相同目的,所以 OpenGL 將兩者視為相同型態。其他還有針對 3D 空間的

操作呼叫,像是位移(Translate)、旋轉(Rotate)和縮放(Scale)…等,也都是矩陣系統

提供的功能,每次的操作都是對現在指定的矩陣型態才有效果。

矩陣系統的設計是用來描述處於 3D 空間物件的位置,不僅在光柵化流程中

使用,光線追蹤對物件的定義也能套用此系統,最重要的就是上段落所說的兩種

型態的矩陣,而整合系統也必須獲得這些矩陣資訊。

幸運的是 Legacy OpenGL 可以透過呼叫 glGet 函式來取得內部狀態,因此前

面段落提到的矩陣操作不需要再重新實作一遍,換言之不必將這些矩陣操作運算

重新導向到整合系統內,因此唯一需要注意的是何時才要擷取矩陣,這個答案也

呼之欲出,回到圖 3 的整合系統流程圖可以發現繪圖指令對應的是整理資料並放

入統一存放區,並不是執行光線追蹤流程,整合系統這樣的行為是因為一定要確

定該畫面在繪製以前場景內容要全部設定完畢,因此擷取矩陣的真正時機就是每

一次的繪製指令呼叫,並且矩陣將不會被用在光柵化管線而是被整合系統的光線

追蹤作為其中的一筆繪圖數據。

16

除了上頁敘述的矩陣功能,OpenGL Utility Library (GLU)也廣泛地被使用在

OpenGL 應用程式中,譬如說 gluPerspective 以及 gluLookAt,前者的功能是指定

觀察視景體(frustum)並定義出 3D 世界坐標系,而後者是指定觀察位置和方向,雖

然兩者沒有透過矩陣功能來改變數值,但實際上 Projection 和 ModelView 矩陣皆

會因為呼叫兩者函式而受到改變,由於 GLU 提供更方便的呼叫模式,通常被使

用的次數不會少於原本矩陣功能,所以需要整合常用的GLU 函式。

比較特別的地方是 Projection 矩陣對於光線追蹤來說比較沒有用處,但指的

是矩陣本身而不是功能性,其實真正有用的是影響該矩陣的參數,如圖 5 所示,

左邊代表原本未套用 Projection 矩陣示意圖,藍色是物體而紅色是視景體,可以

想像的紅色的範圍即是使用者看到的畫面。接下來再看看右邊套用了 Projection

矩陣的示意圖,物體會受到視景體遠近平面的影響而產生形變,而紅色視景體的

部分則壓縮成螢幕的矩形,也就是說畫面更像真實世界的表現了。

圖 5: Projection 矩陣影響視景體

左邊是原本 3D 空間物件分布,右邊是套用了矩陣後的變化,由於針對視景體做 修正,藍色物件會因距離切平面的遠近而產生形變,有如現實世界中觀察物體的

現象。 圖片引用(3,4)

17

拉回到剛剛提到的矩陣問題,光線追蹤需要的是如何在 3D 場景中定義每個

像素取樣的方式也就是光線出發的方向以及取樣間格的設定,所以 Projection 矩 陣的參數像是視野角度(field of view)、長寬比例(aspect ratio)…等才是擷取的重點。

Client-side vertex arrays

VBO 是 OpenGL 為了更有效率地繪圖而將物件緩衝再送入裝置去運算,藉此

減少來回呼叫延遲,而相對於現今modern OpenGL(3.3 版本以上)將 VBO 應用在 shader,以前 legacy OpenGL 的 VBO 是以 client-side 的概念用在光柵化固定管線。

在 client-side 的概念中必須先呼叫 glEnableClientState 來啟動某類別的服務,

舉個例子來說,若現在VBO 包含了頂點資料以及顏色資料,那麼 client-side 必須

要啟動 GL_VERTEX_ARRAY 和 GL_COLOR_ARRAY 兩個列舉型態,這樣在繪

圖管線進行時此 VBO 才會抓取頂點和顏色作為輸入。

上述提到 client-side 掌控哪些服務狀態要被啟用,而對於整合系統來說也要

獲得這些狀態的資訊,因此採取的作法是重新實作相同功能,唯一改變的僅是從

光柵化管線變成給光線追蹤來做使用。

除了 client-side 系統之外,VBO 也是整合系統要獲取的對象,無論是頂點、

顏色或法向量在固定功能呼叫系統中都有專門處理的函式,換個方式來說,每當 VBO 建立後,OpenGL 不會知道使用者會把它拿來做什麼用途,而且資料設定的

方式也以宣告緩衝區的大小以及起始指標來複製指定記憶體區塊,最後直到呼叫

18

了剛剛提到的專門處理函式像是處理頂點的 glVertexPointer,這樣 VBO 才會被用

來做指定的頂點分析,根據位元的位移長度來抓取每筆頂點資料在記憶體區塊的

位置,另外顏色和法向量設定也是相同的道理。

本整合系統對於 VBO 的處理方式和 client-side 一樣,都是將原本提供給光柵

化管線的功能,轉移到系統內的光線追蹤使用,但並不會立即啟動繪製,而是將

資料放在統一存放區。

Fixed-function lighting

Legacy OpenGL 提供了光照的固定功能,透過 glLightfv 來指定光源的屬性,

最常見的設定是顏色資訊和位置,而根據 GL_LIGHT0 至 GL_LIGHT7 的參數可

以對七個光源做個別設定,原則上系統對光源整合也很直觀,就如前面段落的做

法類似,每當呼叫了光源的設定就將函式導向整合系統做數值紀錄,並作為光線

追蹤前置作業的一環。

Buffer Rendering Capability Lighting GLU Extension

glGenBuffers glVertexPointer glEnableClientState glLightfv gluPerspective rtMaterialEXT glBindBuffer glColorPointer glDisableClientState gluLookAt rtBuildKDTreeEXT glBufferData glNormalPointer glEnable

glDrawArrays glDisable

glFlush

表 1: 整合系統支援呼叫列表

Extension 部分並不是 OpenGL 內建的函式,但由於光線追蹤可依照物體的材質改 變光線的行為,實現反射和折射的效果,因此新增這一類的擴充函式。

19

OpenGL 固定功能支援以及前置準備

上頁表 1 是整合系統目前支援的所有固定功能函式列表,從左至右所列出的

項目在先前的段落皆有詳細介紹,這裡再次強調本篇論文的目標,即是希望能提

供一個光線追蹤整合函式庫使得設計OpenGL 應用程式時可以方便的使用光線追

蹤作為繪製畫面的方法,所以到目前為止的論文內容都是討論如何整合 OpenGL

應用程式中常見的函式,總而言之,整合系統就是為了讓這些函式所提供的參數

以及設定數據都成為光線追蹤kernel 端的輸入,而得到的輸出結果就是顯示在螢

幕上的畫面。另外,上頁表 1 中 Extension 的部分列出的是本整合系統提供的擴

充函式,因兩者繪圖方式的差異勢必會有原本光柵化方法沒有的功能,而這裡提

到的函式後面會再提到更進一步的介紹。

20

相關文件