OpenGL 工作原理
OpenGL 圖形接口的設(shè)計(jì) The Design of the OpenGL Graphics Interface
Mark Segal
Kurt Akeley
Silicon Graphics Computer Systems
2011 N. Shoreline Blvd., Mountain View, CA 94039
Abstract
OpenGL 是一種新興的圖形標(biāo)準(zhǔn),它提供高級(jí)渲染功能,同時(shí) 保持簡單的編程模型。因?yàn)?OpenGL 是僅渲染的,它可以被合 并到任何窗口系統(tǒng)中(并且已經(jīng)被合并到 X 窗口系統(tǒng)和即將發(fā) 布的 Windows 版本中)或者可以在沒有窗口系統(tǒng)的情況下使 用。OpenGL 實(shí)現(xiàn)可以有效地適應(yīng)幾乎任何級(jí)別的圖形硬件, 從基本的幀緩沖區(qū)到最復(fù)雜的圖形子系統(tǒng)。因此,在交互式 3 D 和 2D 圖形應(yīng)用程序中使用它是一個(gè)不錯(cuò)的選擇。
我們描述了這些和其他考慮因素如何控制 OpenGL 中圖形運(yùn)算 符的選擇和表示。復(fù)雜的操作已被避開,取而代之的是對(duì) 3D 和 2D 圖形的基本操作進(jìn)行簡單、直接的控制。然而,更高級(jí) 別的圖形函數(shù)可以從 OpenGL 的低級(jí)運(yùn)算符構(gòu)建,因?yàn)檫@些運(yùn) 算符在設(shè)計(jì)時(shí)就考慮到了這種分層。
CR 類別和主題描述符:I.3.3[計(jì)算機(jī)圖形學(xué)]:圖片圖像生成;I.3.7【計(jì)算機(jī)圖形學(xué)】:三維圖形與寫實(shí)
1 Introduction
計(jì)算機(jī)圖形(尤其是 3D 圖形,尤其是交互式 3D 圖形)正在尋 找越來越多的應(yīng)用程序,從用于個(gè)人計(jì)算機(jī)的簡單圖形程序到用于工作站和超級(jí)計(jì)算機(jī)的復(fù)雜建模和可視化軟件。隨著對(duì)計(jì)算機(jī)圖形學(xué)的興趣不斷增長,人們希望能夠編寫在具有 一系列圖形功能的各種平臺(tái)上運(yùn)行的應(yīng)用程序。圖形標(biāo)準(zhǔn)消 除了為運(yùn)行應(yīng)用程序的每個(gè)平臺(tái)編寫不同的圖形驅(qū)動(dòng)程序的 需要,從而簡化了這項(xiàng)任務(wù)。
為了可行,用于交互式 3D 應(yīng)用程序的圖形標(biāo)準(zhǔn)必須滿足幾個(gè) 標(biāo)準(zhǔn)。它必須能夠在具有不同圖形功能的平臺(tái)上實(shí)現(xiàn),而不會(huì)影響底層硬件的圖形性能,也不會(huì)犧牲對(duì)硬件操作的控制 。它必須提供一個(gè)自然接口,允許程序員簡潔地描述渲染操作。最后,界面必須足夠靈活適應(yīng)擴(kuò)展,以便當(dāng)新的圖形操作變得重要或在新的圖形子系 統(tǒng)中可用時(shí),可以在不破壞原始界面的情況下提供這些操作 。
OpenGL 通過為 3D 圖形渲染的基本操作提供簡單、直接的接口來滿足這些標(biāo)準(zhǔn)。它支持點(diǎn)、線段、多邊形和圖像等基本圖形基元,以及仿射和投影變換和光照計(jì)算等基本渲染操作 。它還支持高級(jí)渲染功能,例如紋理映射和抗鋸齒。
還有其他幾個(gè)提供 API 的系統(tǒng)(Application Programmer's Interface) 用于影響圖形渲染。在 2D 圖形的情 況下,PostScript 頁面描述語言 [5] 已被廣泛接受,使得電子交換相對(duì)容易,并且在一定程度上可以操作包含文本和 2D 圖 形的靜態(tài)文檔。除了提供圖形渲染操作符之外,PostScript 還是一種基于堆棧的編程語言。
X 窗口系統(tǒng) [9] 已成為 UNIX 工作站的標(biāo)準(zhǔn)。程序員使用 X 在圖形顯示上獲得一個(gè)窗口,可以在其中繪制文本或 2D 圖形;X 還提供了一種從鍵盤和鼠標(biāo)等設(shè)備獲取用戶輸入的方法。大 多數(shù)工作站制造商采用 X 意味著單個(gè)程序可以通過簡單地重新編譯程序來生成 2D 圖形或在各種工作站上獲取用戶輸入。這 種集成甚至可以跨網(wǎng)絡(luò)工作:程序可以在一個(gè)工作站上運(yùn)行 ,但在另一個(gè)工作站上顯示并從另一個(gè)工作站上獲取用戶輸入,即使網(wǎng)絡(luò)兩端的工作站是由不同的公司制造的。
對(duì)于 3D 圖形,有幾個(gè)系統(tǒng)正在使用中。一個(gè)相對(duì)知名的系統(tǒng) 是 PHIGS(程序員的分層交互式圖形系統(tǒng))。PHIGS 基于 GK S[6](圖形內(nèi)核系統(tǒng)),是一個(gè) ANSI(美國國家標(biāo)準(zhǔn)協(xié)會(huì)) 標(biāo)準(zhǔn)。PHIGS(及其后代 PHIGS+[11])提供了一種操作和繪制 3D 對(duì)象的方法,方法是將對(duì)象描述和屬性封裝到顯示列表中,然后在顯示或操作對(duì)象時(shí)引用該列表。顯示列表的一個(gè)優(yōu)點(diǎn)是即使要顯示多次,復(fù)雜對(duì)象也只需要描述一次。如果要顯示的對(duì)象必須通過低帶寬通道(例如網(wǎng)絡(luò))傳輸,這一點(diǎn)尤其重要。顯示列表的一個(gè)缺點(diǎn)是,如果由于用戶交互而不斷修改對(duì)象,則可能需要相當(dāng)大的努力來重新指定對(duì)象。P HIGS 和 PHIGS+(以及 GKS)的另一個(gè)困難是缺乏對(duì)高級(jí)渲染功能(如紋理映射)的支持。PEX[10] 擴(kuò)展了 X 以包含操縱和繪制 3D 對(duì)象的能力。
(PEXlib[7] 是一個(gè)使用 PEX 協(xié)議的 API。)最初基于 PHIGS,PEX 允許立即模式渲染,這意味著對(duì)象可以按描述的方式顯示,而不必先完成顯示列表。PEX 目前缺乏高級(jí)渲染功能(盡管提供此類功能的兼容版本尚未設(shè)計(jì)),并且僅適用于 X 的用戶。然而,從廣義上講,描述圖形對(duì)象以使用 PEX(或者更確切地說,PEXlib)進(jìn)行渲染的方法類似于 OpenGL 提供的那些。
與 OpenGL 和 PEXlib 一樣,Renderman[16] 是一種 API,它提供了一種渲染幾何對(duì)象的方法。然而,與這些界面不同的是 ,Renderman 提供了一種編程語言(稱為著色語言)來描述這些對(duì)象在繪制時(shí)如何出現(xiàn)。這種可編程性允許生成看起來非常逼真的圖像,但在大多數(shù)圖形加速器上實(shí)現(xiàn)是不切實(shí)際的,這使得 Renderman 成為交互式 3D 圖形的糟糕選擇。
最后,作為描述高級(jí)圖形對(duì)象的方法的結(jié)果,有一些 API 提供對(duì) 3D 渲染的訪問。其中最主要的是 HOOPS[17] 和 IRISInvent or[15]。這些接口提供的對(duì)象通常比使用 PEXlib 或 OpenGL 等 API 描述的簡單幾何圖形更復(fù)雜;它們可能不僅包括幾何圖形 ,還包括有關(guān)它們?nèi)绾卫L制以及它們?nèi)绾螌?duì)用戶輸入作出反應(yīng)的信息。
HOOPS 和 Inventor 將程序員從單個(gè)繪圖操作的繁瑣描述中解 放出來,但對(duì)復(fù)雜對(duì)象的簡單訪問通常意味著失去對(duì)渲染的精細(xì)控制(或至少使這種控制變得困難)。在任何情況下,OpenGL 都可以為構(gòu)建此類更高級(jí)別的 API 提供良好的基礎(chǔ)。
2 OpenGL
在本節(jié)中,我們將簡要介紹 OpenGL。更全面的描述,請(qǐng)讀者參考 [8] 或 [13]。
OpenGL 將圖元繪制到幀緩沖區(qū)中,并受多種可選模式的影響 。每個(gè)圖元都是一個(gè)點(diǎn)、線段、多邊形、像素矩形或位圖。 每種模式都可以獨(dú)立改變;一個(gè)模式的設(shè)置不會(huì)影響其他的設(shè)置 (盡管許多模式可能會(huì)相互作用以確定最終在幀緩沖區(qū)中結(jié)束的內(nèi)容)。通過以函數(shù)或過程調(diào)用的形式發(fā)出命令來設(shè)置模式、指定圖元和其他 OpenGL 操作。

圖 1 顯示了 OpenGL 的示意圖。命令在左側(cè)輸入 OpenGL。大多數(shù)命令可以累積在顯示列表中以供以后處理。否則,命令將通過處理管道有效發(fā)送。
第一階段提供了一種通過評(píng)估輸入值的多項(xiàng)式函數(shù)來逼近曲線和曲面幾何形狀的有效方法。下一階段對(duì)頂點(diǎn)描述的幾何圖元進(jìn)行操作:點(diǎn)、線段和多邊形。在這個(gè)階段,頂點(diǎn)被變換和點(diǎn)亮,圖元被裁剪到一個(gè)視錐體中,為下一個(gè)階段光柵化做準(zhǔn)備。光柵器使用點(diǎn)、線段或多邊形的二維描述生成一系列幀緩沖區(qū)地址和值。這樣產(chǎn)生的每個(gè)片段都被饋送到下一個(gè)階段,在它們最終改變幀緩沖區(qū)之前對(duì)各個(gè)片段執(zhí)行操作。這些操作包括基于傳入和先前存儲(chǔ)的深度值(以實(shí)現(xiàn)深度緩沖)對(duì)幀緩沖區(qū)進(jìn)行條件更新,將傳入的片段顏色與存儲(chǔ)的顏色混合,以及對(duì)片段值進(jìn)行屏蔽和其他邏輯操作。
最后,像素矩形和位圖繞過管道的頂點(diǎn)處理部分,通過光柵化直接將一個(gè)片段塊發(fā)送到各個(gè)片段操作,最終導(dǎo)致一個(gè)像素塊被寫入幀緩沖區(qū)。值也可以從幀緩沖區(qū)讀回或從幀緩沖區(qū)的一部分復(fù)制到另一部分。這些傳輸可能包括某種類型的解碼或編碼。
3 設(shè)計(jì)注意事項(xiàng)
設(shè)計(jì)任何 API 都需要在許多一般因素之間進(jìn)行權(quán)衡,例如完成常見操作的簡單性與通用性,或者帶有少量參數(shù)的許多命令與帶有許多參數(shù)的少量命令。在本節(jié)中,我們將描述影響 OpenGL 開發(fā)的 3DAPI 設(shè)計(jì)所特有的考慮因素。
3.1 性能 Performance
交互式 3D 圖形的一個(gè)基本考慮因素是性能。渲染一個(gè)復(fù)雜度不高的 3D 場(chǎng)景需要進(jìn)行大量計(jì)算,并且在交互式應(yīng)用程序中 ,通常每秒必須重繪幾次場(chǎng)景。因此,用于交互式 3D 應(yīng)用程序的 API 必須提供對(duì)其使用的圖形硬件功能的有效訪問。但是不同的圖形子系統(tǒng)提供不同的能力,所以必須找到一個(gè)通用的接口。
該界面還必須提供一種打開和關(guān)閉各種渲染功能的方法。這 是必需的,因?yàn)槟承┯布赡懿恢С帜承┕δ?,因此無法為這些功能提供可接受的性能,還因?yàn)榧词褂杏布С郑瑔⒂媚承┕δ芑蚬δ芙M合可能會(huì)顯著降低性能。例如,在生成場(chǎng)景的最終圖像時(shí),慢速渲染可能是可以接受的,但在處理場(chǎng)景中的對(duì)象或調(diào)整視點(diǎn)時(shí),通常需要交互速率。在這種情況 下,性能下降的特征可能對(duì)最終圖像是可取的,但在場(chǎng)景操作期間是不可取的。
3.2 正交性 Orthogonality
由于希望能夠打開和關(guān)閉功能,因此這樣做應(yīng)該對(duì)其他功能幾乎沒有副作用。例如,如果希望使用單一顏色繪制每個(gè)多邊形,而不是在其面上插入顏色,則這樣做不應(yīng)影響如何應(yīng)用光照或紋理。類似地,啟用或禁用任何單個(gè)功能不應(yīng)導(dǎo)致渲染結(jié)果未定義的不一致狀態(tài)。這些類型的特征獨(dú)立性是必要的,它允許程序員輕松地操作特征,而不必為特定的非法或不希望的特征組合生成測(cè)試,這可能需要改變貌似不相關(guān)的特征的狀態(tài)。功能獨(dú)立性的另一個(gè)好處是可以以設(shè)計(jì)界面時(shí)未預(yù)見到 的有用方式組合功能。
3.3 完備性 Completeness
在具有圖形子系統(tǒng)的系統(tǒng)上運(yùn)行的 3D 圖形 API 應(yīng)該提供一些 方法來訪問子系統(tǒng)的所有重要功能。如果某些功能可用但未提供,則程序員被迫使用不同的 API 來獲得缺少的功能。由于兩個(gè) API 之間的交互,這可能會(huì)使應(yīng)用程序復(fù)雜化。
另一方面,如果 API 的實(shí)現(xiàn)在一個(gè)硬件平臺(tái)上提供了某些特性 ,那么一般來說,這些特性應(yīng)該存在于提供 API 的任何平臺(tái)上 。如果這個(gè)規(guī)則被打破,那么在一個(gè)確定可以在不同硬件平臺(tái)上運(yùn)行的程序中使用 API 是很困難的,而不記得確切地在哪 些機(jī)器上支持哪些功能。在沒有適當(dāng)加速的平臺(tái)上,某些功能可能表現(xiàn)不佳(因?yàn)樗鼈兛赡鼙仨氃谲浖袑?shí)現(xiàn)),但至少最終會(huì)出現(xiàn)預(yù)期的圖像。
3.4 互操作性 Interoperability
許多計(jì)算環(huán)境由通過網(wǎng)絡(luò)連接在一起的許多計(jì)算機(jī)(通常由不同的公司制造)組成。在這樣的環(huán)境中,能夠在一臺(tái)機(jī)器上發(fā)出圖形命令并讓它們?cè)诹硪慌_(tái)機(jī)器上執(zhí)行是很有用的( 這種能力是 X 成功的因素之一)。這種能力(稱為互操作性) 要求 API 命令的執(zhí)行模型是客戶端?服務(wù)器(client-server):客戶端發(fā)出命令 ,服務(wù)器執(zhí)行它們。(互操作性還要求客戶端和服務(wù)器共享相同的 API 命令如何編碼以通過網(wǎng)絡(luò)傳輸?shù)母拍睿豢蛻舳?服務(wù)器模型只是一個(gè)先決條件。)當(dāng)然,客戶端和服務(wù)器可能是同一臺(tái)機(jī)器。
由于 API 命令可以通過網(wǎng)絡(luò)發(fā)出,因此要求客戶端和服務(wù)器之間的緊密耦合是不切實(shí)際的。由于網(wǎng)絡(luò)延遲,客戶端可能必須等待一段時(shí)間才能響應(yīng)提交給服務(wù)器的請(qǐng)求(往返),而不需要確認(rèn)的簡單服務(wù)器請(qǐng)求可以緩沖到一個(gè)大組中,以便有效傳輸?shù)椒?wù)端并由服務(wù)端執(zhí)行。
3.5 可擴(kuò)展性 Extensibility
正如在介紹中所討論的,3D 圖形 API 至少在原則上應(yīng)該是可擴(kuò)展的,以包含將來可能會(huì)流行的新圖形硬件功能或算法。 盡管在 API 首次使用很久之后才能衡量此目標(biāo)的實(shí)現(xiàn)情況,但可以采取一些措施來幫助實(shí)現(xiàn)它。API 的正交性是有助于實(shí)現(xiàn)這一目標(biāo)的一個(gè)要素。另一個(gè)是考慮如果有意省略的功能被添加到 API 中,API 會(huì)受到怎樣的影響。
3.6 接受性 Acceptance
看起來設(shè)計(jì)一個(gè)干凈、一致的 3D 圖形 API 本身就足夠了。但除非程序員決定在各種應(yīng)用程序中使用 API,否則設(shè)計(jì) API 將毫無用處。因此,值得考慮設(shè)計(jì)決策對(duì)程序員接受 API 的影響 。
4 設(shè)計(jì)特點(diǎn)
在本節(jié)中,我們將重點(diǎn)介紹 OpenGL 設(shè)計(jì)的一般特征,并使用特定示例對(duì)每個(gè)特征進(jìn)行說明和說明。
4.1 基于 IRISGL
OpenGL 基于 SiliconGraphics 的 IRISGL。雖然設(shè)計(jì)一個(gè)全新 的 API 是可能的,但使用 IRISGL 的經(jīng)驗(yàn)讓我們深入了解了程序員在 3D 圖形 API 中想要和不想要什么。此外,盡可能使 Open GL 與 IRISGL 相似,這使得 OpenGL 更容易被接受;有許多成 功的 IRISGL 應(yīng)用程序,IRISGL 的程序員將很容易切換到 OpenGL。
4.2 Low-Level
OpenGL 的一個(gè)基本目標(biāo)是提供設(shè)備獨(dú)立性,同時(shí)仍允許完全訪問硬件功能。因此,API 提供了對(duì)仍提供設(shè)備獨(dú)立性的最低級(jí)別的圖形操作的訪問。因此,OpenGL 不提供描述或建模復(fù)雜幾何對(duì)象的方法。描述這種情況的另一種方式是說 OpenGL 提供了描述如何渲染復(fù)雜幾何對(duì)象的機(jī)制,而不是描述復(fù)雜對(duì)象本身的機(jī)制。
OpenGL 實(shí)用程序庫
低級(jí) API 的一個(gè)好處是對(duì)應(yīng)用程序必須如何表示或描述高級(jí)對(duì)象沒有要求(因?yàn)?API 中沒有此類對(duì)象的概念)。遵守這一原則意味著基本的 OpenGLAPI 不支持一些傳統(tǒng)上與圖形 API 相關(guān)聯(lián)的幾何對(duì)象。例如,OpenGL 實(shí)現(xiàn)不需要渲染凹多邊形。 這種遺漏的一個(gè)原因是凹多邊形渲染算法必然比渲染凸多邊形的算法復(fù)雜,并且不同 的凹多邊形算法可能適用于不同的領(lǐng)域。特別是,如果要多次繪制凹多邊形,首先將其分解為凸多邊形(或三角形)一 次,然后再繪制凸多邊形會(huì)更有效。省略的另一個(gè)原因是, 要渲染一般的凹多邊形,必須首先知道它的所有頂點(diǎn)。圖形子系統(tǒng)通常不提供具有(幾乎)任意數(shù)量頂點(diǎn)的凹多邊形所需的存儲(chǔ)。另一方面,凸多邊形可以在指定時(shí)簡化為三角形 ,因此需要存儲(chǔ)的頂點(diǎn)不超過三個(gè)。
OpenGL 中低級(jí)和高級(jí)的區(qū)別的另一個(gè)例子是 OpenGL 求值器和 NURBS 之間的區(qū)別。評(píng)估器接口為在 OpenGL 之上構(gòu)建通用多項(xiàng)式曲線和曲面包提供了基礎(chǔ)。在 OpenGL 中提供求值器而不是更復(fù)雜的 NURBS 接口的一個(gè)優(yōu)點(diǎn)是,表示曲線和曲面 的應(yīng)用程序(而不是 NURBS)或利用特殊表面屬性的應(yīng)用程序仍然可以訪問有效的多項(xiàng)式求值器(可以在圖形硬件中實(shí)現(xiàn)),而不會(huì)產(chǎn)生轉(zhuǎn)換為 NURBS 表示的成本。
然而,凹多邊形和 NURBS 是常見且有用的運(yùn)算符,并且它們?yōu)?IRISGL 的用戶所熟悉(至少以某種形式)。因此,作為 OpenGL 實(shí)用程序庫的一部分提供了一個(gè)通用的凹多邊形分解, 它隨每個(gè) OpenGL 實(shí)現(xiàn)一起提供。實(shí)用程序庫還提供了一個(gè)基于 OpenGL 的多項(xiàng)式求值器的接口,用于描述和顯示 NURBS 曲線和曲面(帶有域空間修剪),以及一種渲染球體、圓錐體和圓柱體的方法。實(shí)用程序庫既可用作渲染有用幾何對(duì)象 的方法,也可用作構(gòu)建使用 OpenGL 進(jìn)行渲染的其他庫的模型 。
在客戶端?服務(wù)器環(huán)境中,實(shí)用程序庫引發(fā)了一個(gè)問題:實(shí)用程序庫命令在客戶端轉(zhuǎn)換為 OpenGL 命令;如果服務(wù)器計(jì)算機(jī)比客戶端更強(qiáng)大,則客戶端轉(zhuǎn)換可能在服務(wù)器上更有效地執(zhí)行。這種困境不僅出現(xiàn)在 OpenGL 中,而且出現(xiàn)在客戶端和服務(wù)器可能是不同計(jì)算機(jī)的任何庫中。在 OpenGL 中,基本功能反映了高級(jí)圖形子系統(tǒng)有效執(zhí)行的功能,因?yàn)闊o論服務(wù)器計(jì)算機(jī)相對(duì)于客戶端的功能如何,都假定服務(wù)器的圖形子系統(tǒng)可以有效地執(zhí)行它提供的功能。例如,如果將來圖形子系統(tǒng)通常提供完整的修剪 NURBS 支持,那么此類功能應(yīng)該可能從實(shí)用程序庫遷移到 OpenGL 本身。這樣的更改不會(huì)對(duì) OpenGL API 的其余部分造成任何中斷;另一個(gè)塊將簡單地添加到圖 1 的左側(cè)。
4.3 細(xì)粒度控制器 Fine-Grained Control
為了最大限度地減少對(duì)使用 API 的應(yīng)用程序必須如何存儲(chǔ)和呈現(xiàn)其數(shù)據(jù)的要求,API 必須提供一種方法來指定幾何對(duì)象的各個(gè)組件及其上的操作。需要這種細(xì)粒度的控制,以便可以按任何順序指定這些組件和操作,從而使渲染操作的控制足夠靈活,以適應(yīng)不同應(yīng)用程序的要求。
頂點(diǎn)和相關(guān)數(shù)據(jù)
在 OpenGL 中,大多數(shù)幾何對(duì)象是通過包含一系列坐標(biāo)集來繪制的,這些坐標(biāo)集指定頂點(diǎn)和可選的法線、紋理坐標(biāo)和 glBegin glEnd 命令對(duì)之間的顏色。例如,要指定一個(gè)頂點(diǎn)位于(0,0,0),(0,1,0)and(1,0,1) ,可以這樣寫
glBegin(GL_POLYGON);
glVertex3i( 0, 0, c0);
glVertex3i( 0, 1, 0);
glVertex3i( 1, 0, 1);
glEnd();
每個(gè)頂點(diǎn)可以用兩個(gè)、三個(gè)或四個(gè)坐標(biāo)指定(四個(gè)坐標(biāo)表示 一個(gè)均勻的三維位置)。此外,當(dāng)前法線、當(dāng)前紋理坐標(biāo)和 當(dāng)前顏色可用于處理每個(gè)頂點(diǎn)。OpenGL 在光照計(jì)算中使用法線;當(dāng)前法線是一個(gè)三維向量,可以通過發(fā)送三個(gè)指定它的坐標(biāo)來設(shè)置。顏色可能包含紅色、綠色、藍(lán)色和 alpha 值(當(dāng) OpenGL 已初始化為 RGBA 模式時(shí))或單個(gè)顏色索引值(當(dāng)初 始化指定顏色索引模式時(shí))。一、二、三或四個(gè)紋理坐標(biāo)確定紋理圖像如何映射到圖元上。
每個(gè)指定頂點(diǎn)坐標(biāo)、法線、顏色或紋理坐標(biāo)的命令都有幾種風(fēng)格,以適應(yīng)不同應(yīng)用程序的數(shù)據(jù)格式和坐標(biāo)數(shù)量。數(shù)據(jù)也可以作為參數(shù)列表或作為指向包含數(shù)據(jù)的存儲(chǔ)塊的指針傳遞給這些命令。變體通過助記符后綴來區(qū)分。
使用過程調(diào)用來指定一起定義圖元的每個(gè)單獨(dú)的數(shù)據(jù)組意味著應(yīng)用程序可以以它選擇的任何格式和順序存儲(chǔ)數(shù)據(jù);數(shù)據(jù)不需要以便于呈現(xiàn)給圖形 API 的形式存儲(chǔ),因?yàn)?OpenGL 使用數(shù)據(jù)規(guī)范過程的適當(dāng)組合來適應(yīng)幾乎任何數(shù)據(jù)類型和格式。 該方案的另一個(gè)優(yōu)點(diǎn)是,通過以適當(dāng)?shù)捻樞蚝唵蔚亟M合調(diào)用 ,可以獲得不同的效果。圖 2 顯示了通過指定由三角形的所有頂點(diǎn)繼承的單一顏色獲得的統(tǒng)一顏色三角形的示例;通過在每個(gè)頂點(diǎn)之前重新指定顏色來獲得平滑的陰影三角形。并非所有可能的數(shù)據(jù)格式都受支持(例如,可能不會(huì)為頂點(diǎn)坐標(biāo)提供字節(jié)值),只是因?yàn)閺?IRISGL 的經(jīng)驗(yàn)中發(fā)現(xiàn)并非所有格式都被使用。然而,將來添加缺失的格式將是一項(xiàng)微不足道的工作。
在如此精細(xì)的粒度上使用過程調(diào)用的一個(gè)缺點(diǎn)是,如果過程調(diào)用代價(jià)高昂,可能會(huì)導(dǎo)致性能下降。在這種情況下,為一 次發(fā)送的數(shù)據(jù)塊指定格式的接口可能具有性能優(yōu)勢(shì)。然而, 指定數(shù)據(jù)塊的困難在于,它要么限制應(yīng)用程序以一種受支持的格式存儲(chǔ)其數(shù)據(jù),要么要求應(yīng)用程序?qū)⑵鋽?shù)據(jù)復(fù)制到以其中一種格式結(jié)構(gòu)化的塊中,從而導(dǎo)致效率低下。
(允許由單個(gè)數(shù)據(jù)類型的任意組合產(chǎn)生的任何格式是不切實(shí) 際的,因?yàn)榻M合太多。)
在 OpenGL 中,單個(gè)過程調(diào)用提供的最大靈活性被認(rèn)為比使用 這些調(diào)用所導(dǎo)致的任何低效率更為重要。這一決定的部分原 因是考慮到現(xiàn)代編譯器和計(jì)算機(jī)硬件已經(jīng)改進(jìn)到過程調(diào)用通 常相對(duì)便宜,尤其是與處理調(diào)用中包含的幾何數(shù)據(jù)所需的工作相比 。這是 OpenGL 與 PEX 顯著不同的一個(gè)領(lǐng)域。使用 PEX,圖元 的頂點(diǎn)(和相關(guān)數(shù)據(jù))通常在單個(gè)數(shù)組中同時(shí)呈現(xiàn)。如果事 實(shí)證明細(xì)粒度的過程調(diào)用過于昂貴,那么可能有必要在 Open GLAPI 中添加一些流行的塊格式,或者提供一種機(jī)制來定義 這些格式。

4 .4 Modal
作為細(xì)粒度控制的結(jié)果,OpenGL 維護(hù)了相當(dāng)多的狀態(tài)或模式 ,這些狀態(tài)或模式?jīng)Q定了如何渲染圖元。這種狀態(tài)的出現(xiàn)代替了必須為每個(gè)圖元提供大量信息,這些信息將描述該圖元將受到的所有操作的設(shè)置。用每個(gè)圖元呈現(xiàn)如此多的信息是乏味的,并且會(huì)導(dǎo)致過多的數(shù)據(jù)從客戶端傳輸?shù)椒?wù)器。因 此,除了定義它所需的信息外,基本上沒有信息與圖元一起呈現(xiàn)。相反,相當(dāng)大比例的 OpenGL 命令專門用于控制渲染操作的設(shè)置。
模態(tài) API 的一個(gè)困難出現(xiàn)在單獨(dú)的處理器(或進(jìn)程)在不同的圖元上并行操作的實(shí)現(xiàn)中。在這種情況下,必須將模式更改廣播到所有處理器,以便每個(gè)處理器在處理其下一個(gè)圖元之前接收新參數(shù)。因此,模式更改被串行處理,停止原始處理 ,直到所有處理器都接收到更改,并相應(yīng)地降低性能。在這種系統(tǒng)中減少模式變化影響的一種方法是插入一個(gè)在并行處理器之間分配工作的處理器。該處理器可以緩沖一串模式更改,僅在另一個(gè)圖元最終到達(dá)時(shí)才一次傳輸所有更改 [1]。
處理狀態(tài)更改的另一種方法依賴于定義命名狀態(tài)設(shè)置組,然 后只需提供適當(dāng)?shù)拿Q即可調(diào)用這些設(shè)置(這是 X 和 PEX 采用 的方法)。使用這種方法,命名狀態(tài)設(shè)置的單個(gè)命令會(huì)更改服務(wù)器的設(shè)置。出于多種原因,這種方法被 OpenGL 拒絕了。 在內(nèi)存有限的圖形子系統(tǒng)上跟蹤多個(gè)狀態(tài)向量(每個(gè)可能包 含大量信息)可能是不切實(shí)際的。命名狀態(tài)設(shè)置也與強(qiáng)調(diào)細(xì)粒度控制相沖突;在某些情況下,例如在改變單個(gè)模式的狀態(tài)時(shí),直接傳遞改變比先設(shè)置然后命名所需的狀態(tài)向量更方 便和高效。最后,命名狀態(tài)設(shè)置方法仍可用于 OpenGL 通過在顯示列表中封裝狀態(tài)更改命令(見下文)。
矩陣堆棧
OpenGL 中使用了三種變換矩陣:模型?視圖矩陣,應(yīng)用于頂 點(diǎn)坐標(biāo);紋理矩陣,應(yīng)用于紋理坐標(biāo);以及投影矩陣,它描述了視錐體,并在它們被模型?視圖矩陣轉(zhuǎn)換后應(yīng)用于頂點(diǎn)坐標(biāo)。這些矩陣中的每一個(gè)都是 4x4 。這些矩陣中的任何一個(gè)都可以加載或乘以(be loaded with or multiplied by)一般變換;提供命令來指定旋轉(zhuǎn)、平移和縮放的特殊情況(因?yàn)檫@些情況只需要指定幾個(gè)參數(shù),而不是一般變換所需的 16 個(gè)參數(shù))。一個(gè)單獨(dú)的命令控制一個(gè)模式,該模式指示哪個(gè)矩陣當(dāng)前受到這些操作中的任何一個(gè)的影響。此外,每種矩陣類型實(shí)際上都由一堆可以壓入或彈出的矩陣組成。堆棧頂部的矩陣是應(yīng)用 于坐標(biāo)并受矩陣操作命令影響的矩陣。
由這三個(gè)矩陣堆棧表示的保留狀態(tài)簡化了指定在分層圖形數(shù)據(jù)結(jié)構(gòu)中發(fā)現(xiàn)的轉(zhuǎn)換。其他圖形 API 也使用矩陣堆棧,但通常 僅作為更通用屬性結(jié)構(gòu)的一部分。但是 OpenGL 的獨(dú)特之處在于提供了三種可以用相同的命令操作的矩陣。例如,紋理矩陣可用于有效地旋轉(zhuǎn)或縮放應(yīng)用于圖元的紋理圖像,當(dāng)與透視圖變換結(jié)合使用時(shí),甚至可用于獲得投影紋理效果,例如聚光燈模擬和使用陰影貼圖的陰影效果 [14]。
狀態(tài)查詢和屬性棧
幾乎任何 OpenGL 參數(shù)的值都可以通過適當(dāng)?shù)?get 命令獲得。 還有一堆參數(shù)值可以被壓入和彈出。出于堆疊目的,所有參數(shù)分為 21 個(gè)功能組;這些組的任何組合都可以在一次操作中被推送到屬性堆棧(彈出操作僅自動(dòng)恢復(fù)上次推送的那些值 )。需要 get 命令和參數(shù)堆棧,以便各種庫可以有效地使用 OpenGL,而不會(huì)相互干擾。
4.5 Framebuffer
大多數(shù) OpenGL 要求圖形硬件包含幀緩沖區(qū)。這是一個(gè)合理的要求,因?yàn)閹缀跛薪换ナ綀D形應(yīng)用程序(以及許多非交互式應(yīng)用程序)都在具有幀緩沖區(qū)的系統(tǒng)上運(yùn)行。OpenGL 中的一些操作只能通過使用幀緩沖區(qū)公開它們的實(shí)現(xiàn)來實(shí)現(xiàn)(使用 alpha 混合的透明度和使用深度緩沖的隱藏表面去除是兩個(gè)示例)。盡管 OpenGL 可用于為驅(qū)動(dòng)諸如筆式繪圖儀和矢量顯示器之類的設(shè)備提供信息,但這種使用是次要的。
多通道算法 Multipass Algorithms
使幀緩沖區(qū)顯式化的一個(gè)有用效果是它可以使用多通道算法 ,其中相同的圖元被渲染多次。多通道算法的一個(gè)示例使用累積緩沖區(qū) [3]:一個(gè)場(chǎng)景被渲染多次,每次都有一個(gè)稍微不同的視圖,結(jié)果在幀緩沖區(qū)中取平均值。根據(jù)每個(gè)通道視圖的更改方式,此算法可用于實(shí)現(xiàn)全窗口抗鋸齒、景深效果、運(yùn)動(dòng)模糊或這些的組合。多通道算法在 OpenGL 中很容易實(shí)現(xiàn),因?yàn)樵谕ǖ乐g只需操作少量參數(shù),并且更改這些參數(shù)的值既高效又不會(huì)對(duì)其他必須保持不變的參數(shù)產(chǎn)生副作 用。
不變性 Invariance
對(duì)多通道算法的考慮提出了幀緩沖區(qū)中繪制的內(nèi)容如何受或不受更改參數(shù)值影響的問題。例如,如果改變視點(diǎn)影響了將顏色分配給圖元的方式,則累積緩沖區(qū)算法(accumulation buffer algorithm)將不起作用。舉 一個(gè)更合理的例子,如果某些 OpenGL 功能在硬件中不可用, 那么當(dāng)該功能打開時(shí),OpenGL 實(shí)現(xiàn)必須從硬件切換到軟件。 由于硬件和軟件實(shí)現(xiàn)的細(xì)微差別,這樣的開關(guān)可能會(huì)顯著影響最終到達(dá)幀緩沖區(qū)的內(nèi)容。
OpenGL 規(guī)范不是像素精確的;它沒有指出在給定特定輸入的情況下必須將特定像素設(shè)置為的確切值。原因是這樣的規(guī)范 ,除了困難之外,限制性太強(qiáng)。
不同的實(shí)現(xiàn) OpenGL 在不同的硬件上運(yùn)行,具有不同的浮點(diǎn)數(shù)、光柵化算 法和幀緩沖區(qū)配置。盡管如此,實(shí)現(xiàn)各種多通道算法并期望得到合理的結(jié)果應(yīng)該是可能的。
出于這個(gè)原因,OpenGL 規(guī)范給出了某些不變性規(guī)則,這些規(guī)則規(guī)定了在什么情況下,在給定某些輸入的情況下,一個(gè)特定的實(shí)現(xiàn)可能會(huì)得到相同的結(jié)果(不同系統(tǒng)上的實(shí)現(xiàn)永遠(yuǎn)不需要在給定相同輸入的情況下產(chǎn)生相同的結(jié)果)。這些規(guī)則通常表明,更改控制操作的參數(shù)不會(huì)因任何其他操作而影響結(jié)果,但在打開或關(guān)閉操作時(shí)不需要這種不變性。這使得實(shí)現(xiàn)可以在調(diào)用模式時(shí)從硬件切換到軟件而不破壞不變性。另 一方面,即使在切換某種模式時(shí),程序員可能仍然希望保持不變。
為了適應(yīng)這種情況,不變性規(guī)則所涵蓋的任何操作都允許對(duì)其控制參數(shù)進(jìn)行設(shè)置,從而使操作即使在打開時(shí)也像關(guān)閉一樣。例如,可以打開或關(guān)閉一個(gè)比較,但是當(dāng)打開時(shí),執(zhí)行的比較可以設(shè)置為始終(或永遠(yuǎn))通過。
4.6 不可編程
OpenGL 不提供編程語言。它的功能可以通過打開或關(guān)閉操作或?yàn)椴僮髦付▍?shù)來控制,但渲染算法本質(zhì)上是固定的。這 個(gè)決定的一個(gè)原因是,出于性能原因,圖形硬件通常被設(shè)計(jì)為以特定順序應(yīng)用某些操作。用任意算法替換這些操作通常是不可行的??删幊绦詫⑴c保持 API 接近硬件相沖突,從而與 最大化性能的目標(biāo)相沖突。
圖形管道和每個(gè)片段的操作
OpenGL 中的命令執(zhí)行模型是具有固定拓?fù)涞牧魉€模型(盡管階段可能會(huì)被切入或切出)。該管道旨在模仿圖形子系統(tǒng)的組織。例如,流水線的最后階段包括在最終將片段放入幀緩沖區(qū)之前對(duì)片段進(jìn)行一系列測(cè)試和修改。為了在短時(shí)間內(nèi)繪制復(fù)雜的場(chǎng)景,許多片段必須在到達(dá)幀緩沖區(qū)的途中經(jīng)過這些最后階段,幾乎沒有時(shí)間來處理每個(gè)片段。如此高的填充率需要專用硬件,這些硬件只能在對(duì)外部數(shù)據(jù)的訪問最少的情況下執(zhí)行固定操作。
盡管片段操作是有限的,但是通過適當(dāng)?shù)亟M合操作可以獲得許多有趣和有用的效果。OpenGL 提供的每片段操作包括
- alpha 混合:根據(jù) alpha 值將片段的顏色與幀緩沖區(qū)中對(duì)應(yīng)像素的顏色混合;
- 深度測(cè)試:將與片段關(guān)聯(lián)的深度值與幀緩 沖區(qū)中已經(jīng)存在的相應(yīng)值進(jìn)行比較,并根據(jù)比較結(jié)果丟棄或保留片段;
- 模板測(cè)試:將參考值與存儲(chǔ)在幀緩沖區(qū)中的相應(yīng)值 進(jìn)行比較,并根據(jù)比較結(jié)果更新值或丟棄片段。
Alpha 混合可用于實(shí)現(xiàn)透明度或在抗鋸齒時(shí)將片段的顏色與背景的顏色混合;深度測(cè)試可以影響深度緩沖(從而去除隱藏的表面);模板測(cè)試可用于多種效果 [12],包括突出干擾區(qū)域和簡單的 CSG(構(gòu)造實(shí)體幾何)操作。這些(和其他)操 作可以組合以實(shí)現(xiàn),例如,去除隱藏表面的透明干涉區(qū)域, 或任何數(shù)量的其他效果。
OpenGL 圖形流水線還在圖元之間引入了一種正交性。每個(gè)頂點(diǎn),無論它屬于一個(gè)點(diǎn)、線段還是多邊形圖元,都以相同的方式處理:它的坐標(biāo)被轉(zhuǎn)換并且光照(如果啟用)為它分配 一個(gè)顏色。由這些頂點(diǎn)定義的圖元隨后被光柵化并轉(zhuǎn)換為片段,位圖或圖像矩形圖元也是如此。所有片段,無論其來源如何,都一視同仁。操作之間的這種同質(zhì)性從管道中刪除了不需要的特殊情況(對(duì)于每個(gè)原始類型)。它還使不同圖元在同一場(chǎng)景中的組合變得自然,而無需為每種圖元類型設(shè)置特殊模式。
4.7 幾何和圖像
OpenGL 支持處理 3D(和 2D)幾何和 2D 圖像。與幾何一起使用的 API 還應(yīng)提供對(duì)寫入、讀取和復(fù)制圖像的支持,因?yàn)閹缀魏蛨D像經(jīng)常結(jié)合在一起,例如當(dāng) 3D 場(chǎng)景覆蓋在背景圖像上時(shí) 。許多應(yīng)用于由幾何圖元產(chǎn)生的片段的每片段操作同樣適用 于對(duì)應(yīng)于圖像中像素的片段,從而可以輕松地將圖像與幾何 混合。例如,可以使用 alpha 混合將三角形與圖像混合。OpenGL 支持多種圖像格式和對(duì)圖像組件(例如查找表)的操作 ,以提供圖像處理的靈活性。
紋理映射
紋理映射通過有效地將圖像應(yīng)用于幾何圖形,在幾何圖形和 圖像之間提供了重要的聯(lián)系。OpenGL 通過為指定紋理圖像和為幀緩沖區(qū)指定的圖像提供相同的格式來明確這種耦合。除了有助于為場(chǎng)景添加真實(shí)感(圖 3a)外,紋理映射還可用于實(shí)現(xiàn)許多其他有用的效果 [4]。圖 3b 和 3c 顯示了兩個(gè)示例,其中索引紋理圖像的紋理坐標(biāo)是從頂點(diǎn)坐標(biāo)生成的。OpenGL 的正交性使得通過紋理映射實(shí)現(xiàn)這種效果只需啟用適當(dāng)?shù)哪J讲⒓虞d適當(dāng)?shù)募y理圖像,而不會(huì)影響場(chǎng)景的底層規(guī)范。
4.8 立即模式和顯示列表
OpenGL 命令解釋的基本模型是立即模式,在這種模式下,服務(wù)器收到命令后立即執(zhí)行;例如,頂點(diǎn)處理甚至可能在它所屬的圖元的規(guī)范完成之前就開始了。即時(shí)模式執(zhí)行非常適用于圖元和模式不斷變化的交互式應(yīng)用程序。在 OpenGL 中,立即模式提供的細(xì)粒度控制被盡可能地采用:即使是單獨(dú)的照明參數(shù)(例如材質(zhì)的漫反射顏色)和紋理圖像也可以使用具有即時(shí)效果的單獨(dú)命令進(jìn)行設(shè)置。
雖然立即模式提供了靈活性,但如果必須重新指定不變的參數(shù)或?qū)ο?,它的使用可能?huì)效率低下。為了適應(yīng)這種情況,OpenGL 提供了顯示列表。顯示列表封裝了一系列 OpenGL 命令 (除了少數(shù)幾個(gè) OpenGL 命令可以放在顯示列表中),并存儲(chǔ)在服務(wù)器上。顯示列表在指定時(shí)由應(yīng)用程序賦予一個(gè)數(shù)字名稱;應(yīng)用程序只需命名顯示列表即可使服務(wù)器有效地執(zhí)行列表中包含的所有命令。這種機(jī)制為應(yīng)用程序提供了一種直接 、有效的方法,即使這些相同的命令必須多次執(zhí)行,也只需一次將一組命令傳輸?shù)椒?wù)器。
顯示列表優(yōu)化
將命令累積到一個(gè)組中以重復(fù)執(zhí)行提供了優(yōu)化的可能性。例如,考慮指定紋理圖像。紋理圖像通常很大,每當(dāng)重新指定圖像時(shí),都需要從客戶端到服務(wù)器(或從服務(wù)器到其圖形子 系統(tǒng))的大量數(shù)據(jù)傳輸,因此可能很慢。出于這個(gè)原因,一 些圖形子系統(tǒng)配備了足夠的存儲(chǔ)空間來同時(shí)保存多個(gè)紋理圖像。如果紋理圖像定義被放置在顯示列表中,那么服務(wù)器 能能夠在指定圖像時(shí)僅加載一次該圖像。當(dāng)調(diào)用(或重新調(diào)用)顯示列表時(shí),服務(wù)器簡單地向圖形子系統(tǒng)指示它應(yīng)該使用已經(jīng)存在于其內(nèi)存中的紋理圖像,從而避免重新指定整個(gè)圖像的開銷。
像這樣的示例表明需要優(yōu)化顯示列表才能獲得最佳性能。在紋理圖像加載的情況下,服務(wù)器應(yīng)識(shí)別顯示列表包含紋理圖像信息并適當(dāng)?shù)厥褂迷撔畔?。這種期望給 OpenGL 實(shí)現(xiàn)者帶來了負(fù)擔(dān),以確保盡可能有效地處理特殊的顯示列表案例。它還增加了應(yīng)用程序編寫人員的負(fù)擔(dān),讓他們知道在可以提高性能的情況下使用顯示列表。另 一種可能性是為在立即模式下表現(xiàn)不佳的功能引入特殊命令 。但是這種專門化會(huì)使 API 變得混亂,并模糊即時(shí)模式和顯示列表之間的明顯區(qū)別。
顯示列表層次結(jié)構(gòu)
顯示列表可以在 OpenGL 中重新定義,但不能編輯。缺少編輯簡化了服務(wù)器上的顯示列表內(nèi)存管理,消除了此類管理可能帶來的損失。然而,一個(gè)顯示列表可能會(huì)調(diào)用其他列表。因此,可以通過以下方式獲得類似于顯示列表編輯的效果:(1) 構(gòu)建調(diào)用多個(gè)從屬列表的列表;(2) 重新定義下級(jí)列表。這種重新定義在細(xì)粒度上是可能的:從屬顯示列表可能包含任何內(nèi)容(甚至什么都沒有),包括僅單個(gè)頂點(diǎn)或顏色命令。
沒有自動(dòng)保存或恢復(fù)與顯示列表執(zhí)行相關(guān)的模式。(如果需要,可以通過在顯示列表中封裝適當(dāng)?shù)拿顏盹@式地執(zhí)行這種保存和恢復(fù)。)這允許在執(zhí)行顯示列表時(shí)獲得盡可能高的性能,因?yàn)閹缀鯖]有與執(zhí)行相關(guān)的開銷。它還簡化了控制顯示列表層次結(jié)構(gòu)的模式行為:只有明確設(shè)置的模式才會(huì)受到影響。顯示列表中缺少自動(dòng)模式行為也有一個(gè)缺點(diǎn):很難并行執(zhí)行顯示列表,因?yàn)樵谝粋€(gè)顯示列表中設(shè)置的模式必須在 執(zhí)行以下顯示列表之前生效。在 OpenGL 中,顯示列表通常不用于定義整個(gè)場(chǎng)景或場(chǎng)景的復(fù)雜部分,而是用于封裝經(jīng)常重復(fù)的模式設(shè)置命令組(例如描述紋理圖像)或描述簡單幾何的命令(例如,近似圓環(huán)的多邊形)。
4.9 深度緩沖區(qū)
唯一直接提供的隱藏面去除方法是深度(或 Z)緩緩沖區(qū)。這個(gè)假設(shè)與包含幀緩沖區(qū)的圖形硬件一致。其他隱藏表面去除方法可以與 OpenGL 一起使用(例如,BSP 樹 [2] 與畫家算法相結(jié)合),但假設(shè)硬件從不支持此類方法,因此 OpenGL 不需要明確支持。
4.10 局部著色
OpenGL 提供的唯一著色方法是本地的。也就是說,不直接支持用于確定表面顏色的方法,例如需要從場(chǎng)景的其他部分獲取信息的光線追蹤或輻射度。原因是這樣的方法需要全局場(chǎng)景數(shù)據(jù)庫的知識(shí),但到目前為止,專門的圖形硬件被構(gòu)建為本地化操作的管道,并且不提供存儲(chǔ)和遍歷表示復(fù)雜場(chǎng)景所需的大量數(shù)據(jù)的設(shè)施。僅當(dāng)著色可以預(yù)先計(jì)算并且在將圖形 對(duì)象傳輸?shù)?OpenGL 之前與圖形對(duì)象關(guān)聯(lián)的結(jié)果時(shí),才可以將 全局著色方法與 OpenGL 一起使用。

4.11 僅渲染
OpenGL 僅提供對(duì)渲染操作的訪問。沒有從鍵盤和鼠標(biāo)等設(shè)備獲取用戶輸入的設(shè)施,因?yàn)轭A(yù)計(jì)任何運(yùn)行 OpenGL 的系統(tǒng)(特別是窗口系統(tǒng))都必須已經(jīng)提供這些設(shè)施。此外,OpenGL 命 GLX Client GLX 令對(duì)幀緩沖區(qū)的影響最終由分配幀緩沖區(qū)資源的窗口系統(tǒng)( Xlib Direct 如果有的話)控制。窗口系統(tǒng)確定 OpenGL 可以訪問幀緩沖區(qū) OpenGL 的哪些部分,并向 OpenGL 傳達(dá)這些部分的結(jié)構(gòu)。這些考慮使 Renderer OpenGL 窗口系統(tǒng)獨(dú)立。
**X 中的集成 **
X 提供了一個(gè)過程接口和一個(gè)網(wǎng)絡(luò)協(xié)議,用于創(chuàng)建和操作幀緩沖區(qū)窗口以及將某些 2D 對(duì)象繪制到這些窗口中。OpenGL 通過使其成為稱為 GLX 的正式 X 擴(kuò)展而集成到 X 中。GLX 由大約十幾個(gè)調(diào)用(帶有相應(yīng)的網(wǎng)絡(luò)編碼)組成,它們?cè)?X 中提供了 OpenGL 的緊湊、通用嵌入。與其他 X 擴(kuò)展(兩個(gè)示例是 DisplayPostScript 和 PEX)一樣,OpenGL 渲染命令有一個(gè)特定的網(wǎng)絡(luò)協(xié)議封裝在 X 字節(jié)流中。
OpenGL 需要幀緩沖區(qū)的一個(gè)區(qū)域,可以將圖元渲染到該區(qū)域中。在 X 中,這樣的區(qū)域稱為可繪制區(qū)域。窗口,一種可繪制對(duì)象,與描述窗口的幀緩沖區(qū)配置的視覺相關(guān)聯(lián)。在 GLX 中,視覺被擴(kuò)展為包含有關(guān) OpenGL 緩沖區(qū)的信息,這些信息在未修飾的 X 中不存在(深度、模板、累積、前、后等)。
X 還提供了第二種可繪制對(duì)象,即 pixmap,它是一個(gè)離屏幀 GLX 提供了對(duì)應(yīng)于 X 像素圖的 GLX 像素圖,但具有一些視覺效果所指示的附加緩沖區(qū)。GLX 像素圖為 OpenGL 應(yīng)用程序提供 了一種將屏幕外渲染到軟件緩沖區(qū)的方法。
為了使用支持 OpenGL 的可繪制對(duì)象(drawable),程序員創(chuàng)建一個(gè)針對(duì)該可繪制對(duì)象的 OpenGL 上下文。創(chuàng)建上下文時(shí),OpenGL 渲染器的副本會(huì)使用有關(guān)可繪制對(duì)象的視覺信息進(jìn)行初始化。這個(gè) OpenGL 渲染器在概念上(如果不是實(shí)際上)是 X 服務(wù)器的一部分,因此,一旦創(chuàng)建,X 客戶端可以連接到 OpenGL 上下文并發(fā)出 OpenGL 命令(圖 4)??梢詣?chuàng)建多個(gè) OpenGL 上下文,以不同或共享的可繪圖對(duì)象為目標(biāo)。任何支持 OpenGL 的可繪制對(duì)象也可以用于標(biāo)準(zhǔn) X 繪圖(X 未使用的可繪制對(duì)象緩沖區(qū)將被 X 忽略)。

在圖形子系統(tǒng)是其一部分的計(jì)算機(jī)上運(yùn)行的 GLX 客戶端可以避免通過 X 服務(wù)器傳遞 OpenGL 令牌。由于消除了令牌編碼、解碼和分派的開銷,因此這種直接渲染可以提高圖形性能。GLX 支持但不要求直接渲染。直接渲染是可行的,因?yàn)椴恍枰?X 命令和 OpenGL 命令之間保持順序,除非命令顯式同步。因?yàn)?OpenGL 只包含渲染操作,所以它非常適合現(xiàn)有的窗口系統(tǒng)(集成到 Windows 類似于 X 中描述的),而無需復(fù)制窗口系統(tǒng)中已經(jīng)存在的操作(如窗口控制或鼠標(biāo)事件生成)。它還可以利用窗口系統(tǒng)功能,例如離屏渲染,除其他用途外,還可以將 OpenGL 命令的結(jié)果發(fā)送到打印機(jī)。窗口系統(tǒng)提供的渲染操作甚至可以穿插在 OpenGL 中。
4.12 API 不是協(xié)議
PEX 主要被指定為網(wǎng)絡(luò)協(xié)議;PEXlib 是通過 API 呈現(xiàn)該協(xié)議。OpenGL,另一方面,主要被指定為一個(gè) API;當(dāng) OpenGL 嵌入到需要協(xié)議的系 統(tǒng)(如 X)中時(shí),API 以指定的網(wǎng)絡(luò)協(xié)議編碼。這種偏好的一個(gè)原因是應(yīng)用程序程序員使用 API 而不是協(xié)議。另一個(gè)是不同的平臺(tái)可能接受不同的協(xié)議(X 對(duì) X 擴(kuò)展使用的協(xié)議施加了某 些約束,而其他窗口系統(tǒng)可能會(huì)施加不同的約束)。這意味著 API 在平臺(tái)上是不變的,即使協(xié)議不能,因此可以使用相同的源代碼(至少對(duì)于 OpenGL 部分),而不用考慮任何特定的協(xié)議。此外,當(dāng)客戶端和服務(wù)器是同一臺(tái)計(jì)算機(jī)時(shí),OpenGL 命令可以直接傳輸?shù)綀D形子系統(tǒng),而無需轉(zhuǎn)換為通用編碼。
不同系統(tǒng)之間的互操作性不會(huì)因偏愛 API 規(guī)范而不是協(xié)議規(guī)范而受到損害。在一個(gè)制造商的實(shí)現(xiàn)下運(yùn)行的 OpenGL 客戶端連接到另一個(gè)制造商的 OpenGL 服務(wù)器的測(cè)試提供了極好的結(jié)果 。
5 示例:三種文本
為了說明 OpenGL 在執(zhí)行不同類型的渲染任務(wù)方面的靈活性, 我們概述了用于顯示文本的特定任務(wù)的三種方法。這三種方法是:使用位圖,使用線段生成輪廓文本,以及使用紋理生成抗鋸齒文本。
第一種方法將字體定義為一系列顯示列表,每個(gè)顯示列表都包含一個(gè)位圖:
for i = start + ’a’ to start + ’z’ {
glBeginList(i);
glBitmap( ... );
glEndList();
}
glBitmap 指定指向位圖編碼的指針和指示位圖相對(duì)于先前和 后續(xù)位圖如何定位的偏移量。在 GLX 中,這樣定義多個(gè)顯示列表的效果也可以通過調(diào)用 glXUseXFont 來實(shí)現(xiàn)。glXUseXFont 生成許多顯示列表,每個(gè)顯示列表都包含來自指定 X 字體的單個(gè)字符的位圖(和關(guān)聯(lián)的偏移量)。在任何一種情況下 ,其原點(diǎn)是位置在 3D 中的投影的字符串“位圖文本”由
glRasterPos3i(x, y, z);
glListBase(start);
glCallLists("Bitmapped Text",14,GL_BYTE);
參見圖 5a。glListBase 設(shè)置顯示列表基數(shù),以便后續(xù) glCallLi sts 引用剛剛定義的字符。glCallLists 調(diào)用數(shù)組中指定的一系 列顯示列表;將數(shù)組中的每個(gè)值添加到顯示列表庫中,以獲 得要使用的顯示列表的編號(hào)。在這種情況下,數(shù)組是表示字 符串的字節(jié)數(shù)組。glCallLists 的第二個(gè)參數(shù)表示字符串的長 度;第三個(gè)參數(shù)表示字符串是一個(gè) 8 位字節(jié)數(shù)組(16 位和 32 位整數(shù)可用于訪問超過 256 個(gè)字符的字體)。第二種方法與第 一種方法類似,但使用線段來勾勒每個(gè)字符。每個(gè)顯示列表 包含一系列線段:

glTranslate (o x, oy, 0);
glBegin( GL\_LI NES);
glVertex( .. .) ;
...
glEnd();
glTranslate (dx-ox, dy-oy, 0);
初始 glTranslate 更新轉(zhuǎn)換矩陣以相對(duì)于字符原點(diǎn)定位字符。 最后的 glTranslate 更新該字符的來源,為下一個(gè)字符做準(zhǔn)備 。與前面的示例一樣,使用此方法顯示字符串,但由于線段具有 3D 位置,因此文本可以在 3D 中定向和定位(圖 5b)。 更一般地說,顯示列表可以同時(shí)包含多邊形和線段,并且可以對(duì)它們進(jìn)行抗鋸齒處理。
最后,可以通過創(chuàng)建包含字符數(shù)組的紋理圖像來采用不同的方法。因此,一定范圍的紋理坐標(biāo)對(duì)應(yīng)于紋理圖像中的每個(gè)字符。通過在其頂點(diǎn)繪制一個(gè)具有適當(dāng)紋理坐標(biāo)的矩形,可 以以任何大小和任何 3D 方向繪制每個(gè)字符:
glTranslate(ox, oy, 0);
glBegin(GL_QUADS)
glTexCoord( ... );
glVertex( ... );
...
glEnd();
glTranslate(dx-ox, dy-oy, 0);
如果每個(gè)字符的每組命令都包含在一個(gè)顯示列表中,并且用 于描述紋理圖像本身的命令(以及列表庫的設(shè)置)包含在另 一個(gè)名為 TEX 的顯示列表中,那么字符串“Texturemappedtex t!!”可以通過以下方式顯示:
glCallList(TEX);
glCallLists("Texture mapped text!!",21,GL_BYTE);
這種方法的一個(gè)優(yōu)點(diǎn)是,通過簡單地使用適當(dāng)?shù)募y理過濾, 得到的字符是抗鋸齒的(圖 5c)。
6 Conclusion
OpenGL 是一種用于交互式應(yīng)用程序的 3D 圖形 API。它旨在提 供對(duì)硬件圖形功能的最大訪問權(quán)限,無論此類功能處于什么級(jí)別可用。這種效率源于提供對(duì)基本操作的直接控制的靈活界面。OpenGL 并不強(qiáng)制使用特定的方法來描述 3D 對(duì)象以及它們應(yīng)該如何顯示,而是提供了可以渲染這些對(duì)象(無論如何描述)的基本方法。因?yàn)?OpenGL 對(duì) 3D 渲染施加了最小結(jié)構(gòu) ,所以它為構(gòu)建用于處理結(jié)構(gòu)化幾何對(duì)象的庫提供了一個(gè)極好的基礎(chǔ),無論特定結(jié)構(gòu)可能是什么。
高性能、特性正交性 、互操作性、在各種系統(tǒng)上的可實(shí)現(xiàn)性和可擴(kuò)展性的目標(biāo)推動(dòng)了 OpenGLAPI 的設(shè)計(jì)。我們已經(jīng)展示了這些和其他考慮因素對(duì) OpenGL 中呈現(xiàn)操作的影響。結(jié)果是一個(gè)簡單的 API,幾 乎沒有特殊情況,應(yīng)該易于在各種應(yīng)用程序中使用。
OpenGL 的未來工作可能集中在通過優(yōu)化改進(jìn)實(shí)現(xiàn),并擴(kuò)展 A PI 以處理圖形硬件提供的新技術(shù)和功能??赡馨暮蜻x對(duì)象是圖像處理運(yùn)算符、新的紋理映射功能以及其他基本幾何圖元,例如球體和圓柱體。我們相信,在設(shè)計(jì) OpenGLAPI 時(shí)所采取的謹(jǐn)慎措施將使這些以及其他擴(kuò)展變得簡單,并將導(dǎo)致 OpenGL 在未來許多年中仍然是一個(gè)有用的 3D 圖形 API。
References
[1] Kurt Akeley. RealityEngine graphics. In SIGGRAPH 93 Conference Proceedings, pages 109–116, August 1993.
[2] H. Fuchs, Z. M. Kedem, and B. F. Naylor. On visible surface generation by a priori tree structures. Computer Graphics (SIGGRAPH ’80 Proceedings), 14(3):124–133, July 1980.
[3] Paul Haeberli and Kurt Akeley. The accumulation buffer: Hardware support for high-quality rendering. Computer Graphics (SIGGRAPH ’90 Proceedings), 24(2):309–318, July 1990.
[4] Paul Haeberli and Mark Segal. Texture mapping as a fundamental drawing primitive. In Proceedings of the Fourth Eurographics Workshop on Rendering, pages 259–266, June 1993.
[5] Adobe Systems Incorporated. PostScript Language Reference Manual. Addison-Wesley, Reading, Mass., 1986.
[6] International Standards Organization. International standard information processing systems — computer graphics — graphical kernel system for three dimensions (GKS-3D) functional description. Technical Report ISO Document Number 9905:1988(E), American National Standards Institute, New York, 1988.
[7] Jeff Stevenson. PEXlib specification and C language binding, version 5.1P. The X Resource, Special Issue B, September 1992.
[8] Jackie Neider, Mason Woo, and Tom Davis. OpenGL Programming Guide. Addison-Wesley, Reading, Ma., 1993.
[9] Adrian Nye. X Window System User’s Guide, volume 3 of The Definitive Guides to the X Window System. O’Reilly and Associates, Sebastapol, Ca., 1987.
[10] Paula Womack, ed. PEX protocol specification and encoding, version 5.1P. The X Resource, Special Issue A, May 1992.
[11] PHIGS+ Committee, Andries van Dam, chair. PHIGS+ functional description, revision 3.0. Computer Graphics, 22(3):125–218, July 1988.
[12] Jarek Rossignac, Abe Megahed, and Bengt-Olaf Schneider. Interactive inspection of solids: Cross-sections and interferences. Computer Graphics (SIGGRAPH ’92 Proceedings), 26(2):353–360, July 1992.
[13] Mark Segal and Kurt Akeley. The OpenGL graphics system: A specification. Technical report, Silicon Graphics Computer Systems, Mountain View, Ca., 1992.
[14] Mark Segal, Carl Korobkin, Rolf van Widenfelt, Jim Foran, and Paul Haeberli. Fast shadows and lighting effects using texture mapping. Computer Graphics (SIGGRAPH ’92 Proceedings), 26(2):249–252, July 1992.
[15] Paul S. Strauss and Rikk Carey. An object-oriented 3D graphics toolkit. Computer Graphics (SIGGRAPH ’92 Proceedings), 26(2):341–349, July 1992.
[16] Steve Upstill. The RenderMan Companion. Addison-Wesley, Reading, Mass., 1990. [17] Garry Wiegand and Bob Covey. HOOPS Reference Manual, Version 3.0. Ithaca Software, 1991.
本文由mdnice多平臺(tái)發(fā)布