第一章
簡介
我們從這章能學(xué)到什么
- 什么是圖形管線(Graphics Pipeline)以及OpenGL如何與它關(guān)聯(lián)
- OpenGL的起源以及它如何演變成現(xiàn)在的模樣
- 我們在全書中都會使用到的一些基本概念
OpenGL是一種接口汪疮,在我們的應(yīng)用程序中可以用它來訪問或者控制它所運行的設(shè)備的圖形子系統(tǒng)疯暑。它所運行的設(shè)備可以從一個高端圖形工作站到?商用臺式機拉一、視頻游戲主機甚至是一臺智能手機盆犁。將這些設(shè)備的接口標(biāo)準(zhǔn)化到一個子系統(tǒng)可以增強移植性并且可以讓軟件開發(fā)者集中精力創(chuàng)作高品質(zhì)的產(chǎn)品涣楷、制作更有有趣的內(nèi)容以及關(guān)心他們的應(yīng)用的整體效能凿将,而不是陷于他們想要應(yīng)用運行的平臺的細(xì)節(jié)中此叠。這些標(biāo)準(zhǔn)接口被稱為Apllication Programming Interfaces(or APIs)堤撵,OpenGL是其中之一仁讨。這一章簡要介紹OpenGL,描述它如何與底層的圖形子系統(tǒng)關(guān)聯(lián)实昨,并且提供一些OpenGL的起源和演化歷史洞豁。
OpenGL和圖形管線
生成一個高效能并且高容量的產(chǎn)品通常需要兩個東西:可伸縮性(scalability)和并行性(parallelism)。在工廠中荒给,這兩個東西通過使用產(chǎn)品線(production lines)來達(dá)成丈挟。說來就是一個工人安裝汽車的引擎,另一個安裝車門志电,再另一個安裝車輪曙咽。通過將產(chǎn)品的生產(chǎn)階段進行重疊,每一個階段都由一個專業(yè)的專家來專門完成這個任務(wù)溪北,這樣每一個階段就變得更高效桐绒,然后整體生產(chǎn)效率就會提升。同樣之拨,通過在同一時間制作很多汽車茉继,一個工廠可以讓多個工人專門安裝引擎,或者多個工人專門安裝車輪蚀乔,這樣多輛汽車可以同時運作在產(chǎn)品線上烁竭,每輛車都處在完工的不同階段。
計算機圖形是同樣的道理吉挣。我們的程序發(fā)送命令給OpenGL派撕,然后OpenGL以一種盡可能高效的方式將命令發(fā)送給底層的圖形硬件來產(chǎn)生預(yù)期的結(jié)果婉弹。在圖形硬件上可能有很多命令排隊等待執(zhí)行(專業(yè)術(shù)語稱為in flight),其中一些命令可能是完成了一部分的终吼。一個處于后續(xù)階段的命令可以和一個處于前期階段的命令被并發(fā)執(zhí)行镀赌,這樣它們的執(zhí)行就重疊了。此外际跪,計算機圖形通常由很多非常相似的重復(fù)性任務(wù)組成(例如計算一個像素該為什么顏色)并且這些任務(wù)都彼此獨立--意即商佛,一個像素的顏色與另外一個像素的顏色沒有任何關(guān)系。就好像一個車間可以同時制造多個汽車姆打,所以O(shè)penGL可以把你給他的工作拆解開然后用它的基礎(chǔ)元素并行完成良姆。通過組合管線(pipelining)和并行(parallelism),現(xiàn)代圖形處理器超乎想象的性能就被實現(xiàn)了幔戏。
OpenGL的目的是在我們的應(yīng)用程序和底層的圖形子系統(tǒng)中間提供一個抽象層(abstraction layer)玛追,圖形子系統(tǒng)通常是一個硬件加速器(由一個或多個自定義的高性能處理器和專用內(nèi)存、顯示輸出等等構(gòu)成)闲延。這個抽象層可以使我們的應(yīng)用程序不必知曉誰是制造的圖形處理器(或者叫GPU - 圖形處理單元)痊剖、它如何工作、它工作得好不好慨代。當(dāng)然我們的應(yīng)用程序仍然可以獲知這些信息邢笙,重要的是我們的應(yīng)用程序不必如此啸如。
作為一個設(shè)計原則侍匙,OpenGL必須在抽象層次的過高與過低之間取得平衡。一方面叮雳,它必須隱藏不同制造商的產(chǎn)品的區(qū)別(或者同一廠商的不同產(chǎn)品)和平臺相關(guān)的特性想暗,比如:顯示屏分辨率、處理器架構(gòu)帘不、安裝的操作系統(tǒng)等等说莫。另一方面,它的抽象層次要低到可以讓程序員獲得底層硬件的訪問權(quán)限并且充分利用它寞焙。如果OpenGL展現(xiàn)過高的抽象層次储狭,這樣它就可以很容易地用來創(chuàng)造符合它的樣式的程序,但卻很難使用到它未包含的圖形硬件的高級特性捣郊。這種高層次抽象的樣式有一些軟件用到辽狈,如:游戲引擎--為了讓基于它構(gòu)建的游戲訪問到新的圖形硬件特性通常需要對引擎做出很大量的改變。如果抽象層次過低呛牲,應(yīng)用程序需要關(guān)心它們所運行的平臺的架構(gòu)特性刮萌。低層次抽象在比如視頻游戲主機中比較普遍,但這種抽象層次的圖形庫不能跨平臺支持從移動手機到游戲的個人電腦甚至高性能專業(yè)的圖形工作站娘扩。
隨著技術(shù)的發(fā)展着茸,計算機圖形進行了越來越多的研究?壮锻,最佳實踐被開發(fā)出來,瓶頸和需求在變化涮阔,所以O(shè)penGL也必須不斷變化趕上時代猜绣。
大多數(shù)OpenGL實現(xiàn)都基于當(dāng)前最先進的圖形處理單元,可進行多個每秒萬億次浮點運算的運算能力敬特、擁有好多G每秒吞吐量好幾百G的內(nèi)存途事、并且可以驅(qū)動多個幾百萬像素高頻刷新的顯示器。GPU也超級靈活擅羞,以至于可以處理跟圖形完全不沾邊的任務(wù)尸变,比如:物理模擬、人工智能减俏、甚至音頻處理召烂。
如今的GPU由大量的小型可編程處理器(被稱為shader cores)組成,這些shader cores運行一種叫做著色器(shaders)的迷你程序娃承。每個core有相對較低的吞吐量奏夫、在一個或多個時鐘周期內(nèi)處理shader的一條指令,并且一般缺少高級的特性历筝,比如: 無序執(zhí)行酗昼、分支預(yù)測、超標(biāo)量技術(shù)等等梳猪。但每個GPU都可能包含從幾十個到幾千個這樣的core麻削,當(dāng)它們聚集在一起時可以完成一個巨量的工作。圖形系統(tǒng)被分解為多個階段(stages)春弥,每個階段被用一個shader或者固定功能函數(shù)(fixed-function)呛哟、可能可配置的處理區(qū)塊表示。圖示1.1展示了一個精簡的圖形管線的概要匿沛。
![fiture1.1](https://raw.githubusercontent.com/shawhen/OpenGLSuperBible7th-ZHCN/master/%E7%AC%AC%E4%B8%80%E9%83%A8%E5%88%86-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/figures/figure1.1.png)
在圖示1.1中扫责,圓角矩形框(如Vertex fetch)表示固定功能函數(shù)階段,而方角矩形表示可編程的階段逃呼,意即它們會執(zhí)行你提供的著色器鳖孤。實際上有些固定功能函數(shù)階段或者全部的也會真正使用著色器代碼來實現(xiàn)--只不過不是我們提供的代碼,而是通常由GPU廠商當(dāng)做驅(qū)動程序的一部分抡笼、固件或者其他系統(tǒng)性軟件提供苏揣。
OpenGL的起源和演化
OpenGL起源于Silicon Graphics公司和它的IRIS GL。當(dāng)時GL表示(現(xiàn)在仍表示)圖形庫(Graphics Library)的意思并且在很多現(xiàn)代的OpenGL文檔中你會看到術(shù)語"the GL"蔫缸,它表示特定圖形庫("the graphics library")腿准,這也是源于當(dāng)時。Silicon Graphics曾經(jīng)是一家高端圖形工作站生廠商。曾有非常昂貴并且私有專利性的圖形API吐葱。很多其他生廠商制造更便宜的解決方案運行于兼容其他生廠商的API之上街望。90年代早期,SGI意識到可移植性的重要性弟跑,于是他們決意清理IRIS GL灾前,移除API中與特定系統(tǒng)關(guān)聯(lián)的部分并把它當(dāng)做一種開放標(biāo)準(zhǔn)進行發(fā)行,這個開放標(biāo)準(zhǔn)可被任何人無須專利地進行實做孟辑。初見成型的OpenGL第一個版本在1992年6月發(fā)行并被標(biāo)記為OpenGL 1.0哎甲。
同年,SGI幫助成立了OpenGL架構(gòu)評審委員會(OpenGL Architectural Review Board - ARB)饲嗽,原始的成員包含有Compaq,DEC,IBM,Intel以及Microsoft炭玫。很快,其他公司貌虾,諸如: Hewlett Packard, Sun Microsystem, Evans&Sutherland以及Intergraph也加入到委員會中吞加。OpenGL ARB是設(shè)計、控制并且創(chuàng)作OpenGL標(biāo)準(zhǔn)的主體尽狠,現(xiàn)在它是Khronos Group的一部分衔憨,Khronos Group是一個更大的多家公司的聯(lián)合機構(gòu)用以監(jiān)督很多開放標(biāo)準(zhǔn)的開發(fā)。這些原始成員的一些有的不存在了(可能退出商業(yè)市場或者被其他公司收購或合并)袄膏,有的退出了ARB践图。
本書創(chuàng)作的當(dāng)時,OpenGL已發(fā)行有19個版本沉馆。它們的版本號和發(fā)行日期如下(本書講述版本4.5):
Version Publication Date
OpenGL 1.0 1992.1
OpenGL 1.1 1997.1
OpenGL 1.2 1998.3
OpenGL 1.2.1 1998.10
OpenGL 1.3 2001.8
OpenGL 1.4 2002.7
OpenGL 1.5 2003.7
OpenGL 2.0 2004.9
OpenGL 2.1 2006.7
OpenGL 3.0 2008.8
OpenGL 3.1 2009.3
OpenGL 3.2 2009.8
OpenGL 3.3 2010.3
OpenGL 4.0 2010.3
OpenGL 4.1 2010.7
OpenGL 4.2 2011.8
OpenGL 4.3 2012.8
OpenGL 4.4 2013.7
OpenGL 4.5 2014.8
OpenGL核心檔案(Core Profile)
在刀刃技術(shù)(電子芯片切割)的開發(fā)中码党,20年是一個很長的時間。在1992年悍及,頂尖的Intel CPU是80486闽瓢,數(shù)學(xué)協(xié)處理器還是可選的,并且奔騰(Pentium)也還未發(fā)明(至少沒發(fā)行)心赶。蘋果電腦還在使用摩托羅拉68K衍生處理器,后來切換到的PowerPC處理器是1992年下半年才可用缺猛。在商用家用計算機上高性能圖形加速基本什么也不是缨叫。如果你沒有一臺高性能圖形工作站,你可能不會想用OpenGL來干什么事荔燎。軟件渲染主宰世界耻姥,F(xiàn)uture Crew的Unreal示例贏得Assembly的1992示例聚會。對于一臺家用計算機有咨,你能期望的最好的渲染能力就是一些填充的多邊形或者精靈琐簇。1992的家用計算3D圖形藝術(shù)的狀態(tài)如圖示1.2:
![figure 1.2](https://raw.githubusercontent.com/shawhen/OpenGLSuperBible7th-ZHCN/master/%E7%AC%AC%E4%B8%80%E9%83%A8%E5%88%86-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/figures/figure1.2.png)
隨著時間的推移,圖形硬件的價格走低,性能上升以及可用于家用計算機的廉價加速板卡和視頻游戲主機性能提升的一些因素婉商,新的功能和能力在不太昂貴的圖形處理器上展現(xiàn)出來并加入到OpenGL似忧。這些功能的極大一部分由OpenGL ARB成員在擴展(extensions)中進行提案。有一些擴展與其他的擴展和OpenGL現(xiàn)有的功能可以很好的交互丈秩,有一些不能盯捌。同時,新的蘑秽、更好的榨干圖形系統(tǒng)性能的手段被發(fā)明饺著,它們都被加入到OpenGL,于是做同一件事有了多種方案肠牲。
長久以來幼衰,ARB向后兼容上花了很大力氣,現(xiàn)在仍然如此缀雳。但是塑顺,這種向后兼容帶來一個可觀的消耗。在1990年代中期可以很好工作或者其實不是瓶頸的圖形硬件并不能很好適應(yīng)如今的圖形處理器俏险。指定新的功能如何與舊的傳統(tǒng)的功能交互并不容易严拒,而且很多時候使得干凈地引入一個新功能到OpenGL幾近不可能。對于實做OpenGL來說竖独,這種兼容性也變成了一項艱巨的任務(wù)裤唠,它導(dǎo)致驅(qū)動程式更容易出錯,而且圖形廠商也需要花費可觀的精力來維護所有的傳統(tǒng)功能莹痢,而這些功能對圖形技術(shù)的發(fā)展和變革沒有任何用處种蘸。
基于這些原因,在2008年竞膳,ARB決意將OpenGL標(biāo)準(zhǔn)變更為兩份檔案(profile)航瞭。第一個為核心檔案(core profile),它移除了許多傳統(tǒng)功能坦辟,只保留了如今的圖形硬件真正會加速的功能刊侯。這份標(biāo)準(zhǔn)比舊的標(biāo)準(zhǔn)少了好幾百頁,舊的標(biāo)準(zhǔn)稱為兼容檔案(compatibility profile)锉走。兼容檔案維護了從1.0到現(xiàn)今的所有版本的兼容性滨彻。意即1992年編寫的軟體應(yīng)能編譯并且以幾千倍的效率提升運行于現(xiàn)今的圖形卡上。
不過兼容檔案的存在可以讓軟體開發(fā)者為傳統(tǒng)的應(yīng)用添加新功能而不必為了遷移到新的API白費好些年的努力挪蹭。然而核心檔案是大多數(shù)OpenGL專家推薦新的應(yīng)用使用的檔案亭饵。特別是在某些平臺上,新的功能只能在核心檔案下使用梁厉,從其他方面來講辜羊,使用核心檔案的應(yīng)用通常會快于兼容檔案,即使應(yīng)用不經(jīng)過任何修改,僅僅是請求兼容檔案八秃,甚至于只使用核心檔案的功能碱妆。總而言之喜德,如果一個功能在兼容檔案中但從核心檔案中被移除山橄,我們最好就不要使用這個功能。
本書只會涉及到核心檔案舍悯。
圖元(Primitives)航棱、管線(pipelines)、像素(pixels)
正如我們討論過的萌衬,OpenGL的模型就好比一條生產(chǎn)線或者管線饮醇。數(shù)據(jù)流在這個模型中通常是單一路經(jīng)的,數(shù)據(jù)通過我們的程式調(diào)用的命令進入管線的開端秕豫,然后流過一個一個階段直到管線的末端朴艰。在這個路經(jīng)當(dāng)中,管線中的著色器或者固定功能函數(shù)可以從緩沖區(qū)(buffers)或者材質(zhì)(textures)提取更多的數(shù)據(jù)混移,緩沖區(qū)和材質(zhì)是用來在渲染中存取信息的結(jié)構(gòu)祠墅。管線中有一些階段甚至可能會向緩沖區(qū)或者材質(zhì)存入數(shù)據(jù),從而讓應(yīng)用讀寫數(shù)據(jù)甚至反饋發(fā)生了什么歌径。
OpenGL中基本的渲染單元稱為圖元(primitive)毁嗦。OpenGL支持許多圖元類型,但三種基本的可渲染圖元為:點(points)回铛、線(lines)狗准、三角形(triangles)。我們在熒屏上看到的渲染的任何東西都是點茵肃、線和三角形的集合腔长。在應(yīng)用中一般會把復(fù)雜的表面(surfaces)拆解成許多三角形然后發(fā)送給OpenGL通過一個叫做光柵器(rasterizer)的硬件加速器進行渲染。三角形相對來說是非常容易繪制的验残。對于多邊形捞附、三角形通常是凸面的,所以填充規(guī)則很容易設(shè)計和遵循胚膊。凹多邊形總是能拆解成兩個或多個三角形故俐,所以硬件天然地支持直接渲染三角形并且依賴其他子系統(tǒng)將復(fù)雜幾何形體拆解為三角形。光柵器是專門用來將三維形式的三角形轉(zhuǎn)換為在熒屏上進行渲染的像素的硬件紊婉。
點、線以及三角形分別是由一個辑舷、兩個或者三個頂點(vertices)集合組成的喻犁。一個頂點(vertex)就是一個坐標(biāo)空間的點。在我們的場景中,我們主要考慮一個三維坐標(biāo)空間肢础。圖形管線被拆解為主要的兩部分还栓。第一部分是前端(front end),處理頂點和圖元传轰,最后把它們組成為點剩盒、線和三角形傳遞給光柵器。這個過程被稱為圖元組裝(primitive assembly)慨蛙。光柵器處理之后辽聊,幾何圖形已經(jīng)被轉(zhuǎn)變成大量的獨立的像素妥色。這些都是交給后端的(back end)的觅闽,它包括深度(depth)測試和模板(sencil)測試,片段著色(fragment shading)滚朵,混合(blending)以及更新輸出圖像通砍。
隨著我們閱讀本書玛臂,我們會看到如何讓OpenGL開始為我們所用。我們會看到如何創(chuàng)建緩沖區(qū)和材質(zhì)并和我們的程式關(guān)聯(lián)封孙。我們會看到如何編寫著色器來處理我們的數(shù)據(jù)以及如何配置OpenGL的固定功能函數(shù)塊來做我們想做的迹冤。OpenGL其實就是一大串非常簡單的概念,它們互相依存虎忌。擁有堅實的基礎(chǔ)以及對這個系統(tǒng)的概覽是很非常重要的泡徙,在接下來的幾個章節(jié),我們將提供這些呐籽。
總結(jié)
在這一章我們簡單介紹了OpenGL并了解了它的一點起源锋勺、歷史、狀態(tài)和方向狡蝶。我們已經(jīng)看到了OpenGL管線以及本書如何構(gòu)成庶橱。我們提及了一些將會貫穿本書的專業(yè)術(shù)語。在接下來的幾個章節(jié)贪惹,我們會創(chuàng)建第一個OpenGL程式苏章,稍微深入到OpenGL管線的各個階段,并打下一些在計算機圖形世界非常有用的數(shù)學(xué)基礎(chǔ)奏瞬。
Copyright
本書原著為《OpenGL Super Bible》枫绅,版權(quán)歸原作者所有,本譯文僅為愛好者學(xué)習(xí)交流所用硼端。