OpenGL(Open Graphics Library):圖形硬件的軟件接口,將計算機的資源抽象成一個OpenGL對象。對OpenGL對象的操作就是對這些資源的整合和操作。它具有強大的跨編程語言和跨平臺的兼容性。
跨編程語言:OpenGL官方網(wǎng)頁中列出了用于Java、Fortran 90、Perl、Pike、Python、Ada和Visual Basic的多個綁定。
跨平臺:Windows、Mac OS、Linux、Unix。
OpenGL操作的是GPU芯片,關(guān)于窗口系統(tǒng)的view、window并不是OpenGL來操作,而是相對的iOS或Android系統(tǒng)來完成的。
OpenGL是一種圖形應(yīng)用程序編程接口,簡單理解就是開發(fā)圖形庫。
可以用來做:????
????視頻、圖形、圖片處理;????
????2D、3D游戲引擎開發(fā)??
? ? 科學(xué)可視化??
? ? 醫(yī)學(xué)軟件開發(fā)??
? ? CAD(計算機輔助技術(shù))??
? ? 虛擬實境(AR、VR)??
? ? AI人工智能
OpenGL ES(OpenGL for Embedded Systems)是OpenGL的子集。針對移動終端或游戲主機等嵌入式設(shè)備而設(shè)計的,去除了很多不必要和性能較低的API接口。
現(xiàn)在主要 有兩個版本,OpenGL ES 1.x 針對固定管線硬件的,OpenGL ES 2.x 針對可編程管線硬件。OpenGL ES 1.0 是以 OpenGL 1.3 規(guī)范為基礎(chǔ)的,OpenGL ES 1.1 是以 OpenGL 1.5 規(guī)范為基礎(chǔ)的,它們分別又支持 common 和 common lite 兩種profile。lite profile只支持定點定點實數(shù),而common profile既支持定點數(shù)又支持浮點數(shù)。 OpenGL ES 2.0 則是參照 OpenGL 2.0 規(guī)范定義的,common profile發(fā)布于2005-8,引入了對可編程管線的支持。
支持平臺、機型:?
- 支持iPad, iPhone3GS 和后續(xù)版本,以及iPodTouch3代和后續(xù)版本。
- 支持Android平臺從Android 2.2版本開始。
- 支持Android NDK從Android 2.0版本開始。
- 支持BlackBerryPlayBook黑莓。
- 支持Pandora潘多拉控制臺的3D庫。
- 被WebGL支持:瀏覽器支持OpenGL?
- 支持少數(shù)新款Nokia諾基亞手機,比如N900上的Maemo和N8上的Symbian3塞班3系統(tǒng)。??
- 支持多款三星手機,包括Galaxy S和Wave。??
- 使用開發(fā)插件可以支持Palm webOS。? ?
- 支持Archos 愛可視上網(wǎng)本:70 IT, 101 IT。
DirectX:在使基于Windows 的計算機成為運行和顯示具有豐富多媒體元素(例如全色圖形、視頻、3D 動畫和豐富音頻)的應(yīng)用程序的理想平臺。DirectX 包括安全和性能更新程序,以及許多涵蓋所有技術(shù)的新功能。應(yīng)用程序可以通過使用DirectX API 來訪問這些新功能。
DirectX是由很多API組成的,按照性質(zhì)分類,可以分為四大部分,顯示部分、聲音部分、輸入部分和網(wǎng)絡(luò)部分。
????顯示部分
顯示部分擔(dān)任圖形處理的關(guān)鍵,分為DirectDraw(DDraw)和Direct3D(D3D),前者主要負(fù)責(zé)2D圖像加速。它包括很多方面:我們播放mpg、DVD電影、看圖、玩小游戲等等都是用的DDraw,你可以把它理解成所有劃線的部分都是用的DDraw。后者則主要負(fù)責(zé)3D效果的顯示,比如CS中的場景和人物、FIFA中的人物等等,都是使用了DirectX的Direct3D。
????聲音部分:
聲音部分中最主要的API是DirectSound,除了播放聲音和處理混音之外,還加強了3d音效,并提供了錄音功能。我們前面所舉的聲卡兼容的例子,就是利用了DirectSound來解決的。
????輸入部分:
輸入部分DirectInput可以支持很多的游戲輸入設(shè)備,它能夠讓這些設(shè)備充分發(fā)揮最佳狀態(tài)和全部功能。除了鍵盤和鼠標(biāo)之外還可以連接手柄、搖桿、模擬器等。
網(wǎng)絡(luò)部分:
網(wǎng)絡(luò)部分DirectPlay主要就是為了具有網(wǎng)絡(luò)功能游戲而開發(fā)的,提供了多種連接方式,TCP/IP,IPX,Modem,串口等等,讓玩家可以用各種連網(wǎng)方式來進(jìn)行對戰(zhàn),此外也提供網(wǎng)絡(luò)對話功能及保密措施。
Metal:在WWDC?2014 上,Apple為游戲開發(fā)者推出了新的平臺技術(shù) Metal,該技術(shù)能夠為 3D 圖像提高 10 倍的渲染性能,并支持大家熟悉的游戲引擎及公司。
? ? 相對于OpenGL而言,Metal在iOS端的圖形渲染能力上做到了極致。是一種低層次的渲染應(yīng)用程序編程接口,提供了軟件所需的最低層,保證軟件可以運行在不同的圖形芯片上。Metal 提升了 A7 與 A8 處理器效能,讓其性能完全發(fā)揮。
? ? 可以這樣理解,Metal相對于OpenGL ES來說就是swift相對于objective-C。盡管蘋果大力推崇swift,但是還是有大部分開發(fā)者喜歡使用objective-C,甚至在2018年編程語言排名中,objective-C強勢反彈回前十。Metal雖然在極致渲染方面強于OpenGL,但是兼容性能不足,市場占有率和對于開發(fā)者的學(xué)習(xí)吸引力可能弱于OpenGL。只能說未來可期吧~
Metal代表作:支持蘋果Metal技術(shù)?
《現(xiàn)代戰(zhàn)爭5》完成Metal更新,槍戰(zhàn)畫面越發(fā)精致
《狂野飆車8》更新,支持iOS8 Metal圖像引擎特性
OpenGL上下文(Context)
在應(yīng)用程序調(diào)用任何OpenGL指令之前,需要安排首先創(chuàng)建一個OpenGL的上下文。這個上下文是一個非常龐大的狀態(tài)機,保存了OpenGL中的各種狀態(tài),這也是OpenGL指令執(zhí)行的基礎(chǔ)。每一個硬件GPU是個服務(wù)器,每一個繪制上下文對應(yīng)于申請的一個客戶端,一個客戶端維護(hù)著一套狀態(tài)機,如果兩個窗口分別對應(yīng)兩個不同的繪制上下文,則兩個窗口彼此狀態(tài)獨立。
OpenGL的函數(shù)不管在哪個語言中,都是類似C語言一樣的面向過程的函數(shù),本質(zhì)上面都是對OpenGL上下文這個龐大的狀態(tài)機中的某個狀態(tài)或者對象進(jìn)行操作。通過對OpenGL指令的封裝,是可以將OpenGL的相關(guān)調(diào)用封裝成為一個面向?qū)ο蟮膱D形API的。
由于OpenGL上下文是一個巨大的狀態(tài)機,切換上下文往往會產(chǎn)生較大的開銷。但是不同的繪制模塊,可能需要使用完全獨立的狀態(tài)管理。因此,可以在應(yīng)用程序中分別創(chuàng)建多個不同的上下文,在不同的線程中使用不同的上下文,上下文之間共享紋理、緩沖區(qū)等資源。這樣的方案,會比反復(fù)切換上下文,或者大量修改渲染狀態(tài),更加合理高效的。
OpenGL狀態(tài)機
狀態(tài)機理論上是一種機器,其實我們可以這樣去理解,狀態(tài)機描述了一個對象在其生命周期中所經(jīng)歷的各種狀態(tài),狀態(tài)之間的轉(zhuǎn)變,發(fā)生轉(zhuǎn)變的動因,條件以及轉(zhuǎn)變中所執(zhí)行的活動。
為什么說OpenGL是狀態(tài)機?
1. OpenGL可以記錄自己的狀態(tài)(比如:當(dāng)前所使用的顏色、是否開啟了混合功能,等等,這些都是要記錄的)
2. OpenGL可以接收輸入(當(dāng)我們調(diào)用OpenGL函數(shù)的時候,實際上可以看成OpenGL在接收我們的輸入),根據(jù)輸入的內(nèi)容和自己的狀態(tài),修改自己的狀態(tài),并且可以得到輸出(比如我們調(diào)用glColor3f,則OpenGL接收到這個輸入后會修改自己的“當(dāng)前顏色”這個狀態(tài);我們調(diào)用glRectf,則OpenGL會輸出一個矩形)
3. OpenGL可以進(jìn)入停止?fàn)顟B(tài),不再接收輸入。這個可能在我們的程序中表現(xiàn)得不太明顯,不過在程序退出前,OpenGL總會先停止工作的。?
渲染(Rendering)
將圖形/圖像數(shù)據(jù)轉(zhuǎn)換成3D空間圖像操作叫做渲染。例如,在圖片或者視頻進(jìn)行解碼之后,形成了一大堆的二進(jìn)制文件,然后我們將這一堆的二進(jìn)制文件顯示到屏幕上面的過程就可以理解為渲染。
頂點數(shù)據(jù)(Vertex Data)
一個頂點是一個3D坐標(biāo)(也就是x、y、z數(shù)據(jù))。三個3D坐標(biāo)組成一個三角形。而頂點數(shù)據(jù)是用頂點屬性(Vertex Attributes)表示的,它可以包含任何我們希望用的數(shù)據(jù)。
頂點數(shù)組(VertexArray)
頂點是我們在繪制一個圖形的時候,頂點的位置數(shù)據(jù),這個數(shù)據(jù)是可以直接存儲在數(shù)組中或者將其緩存在GPU內(nèi)存(棧區(qū))中的。頂點數(shù)組就是我們在畫畫的時候,最開始畫的一個大致的骨架。在OpenGL中的圖像都是由圖元組成。在OpenGL ES中,有三種圖元:點、線、三角形。我們通過設(shè)定函數(shù)的指針,將頂點數(shù)據(jù)存儲在內(nèi)存中,然后需要繪制的時候,直接從內(nèi)存中取出來使用。這一部分的數(shù)據(jù)其實就是頂點數(shù)組。
頂點緩沖區(qū)(VertexBuffer)
我們上面說了,我們在調(diào)用繪制方法的時候,直接就由內(nèi)存?zhèn)魅腠旤c數(shù)據(jù)。還有一種更加高性能的方法,就是提前分配一快內(nèi)存,將頂點數(shù)據(jù)預(yù)先傳入到顯存當(dāng)中,這部分的顯存,就叫做頂點緩沖區(qū)。值得注意的是,這一塊空間不再內(nèi)存中,而是在顯存的一塊空間中。
管線
因為我們的GPU在處理數(shù)據(jù)的時候,是通過一個固定的順序來的,這個順序不能被打破。類似一個流水線的形式,所以被稱之為管線。
固定管線/存儲著色器
在早期的OpenGL版本,它封裝了很多著色器程序塊內(nèi)置的一段包含了光照、坐標(biāo)變換、裁剪等等諸多功能的固定shader程序來完成,來幫助開發(fā)者來完成圖形的渲染。而開發(fā)者只需要傳入相應(yīng)的參數(shù),就能快速完成圖形的渲染,類似于iOS開發(fā)會封裝很多的API。而我們只需要調(diào)用,就可以實現(xiàn)功能,不需要關(guān)注底層實現(xiàn)原理。OpenGL的使用場景非常豐富,固定管線或存儲著色器無法完成所有業(yè)務(wù),所以將相關(guān)部分開放成可編程狀態(tài)。
著色器程序(Shader)
將固定渲染管線架構(gòu)變成可編程渲染管線。OpenGL在實際調(diào)?繪制函數(shù)之前,還需要指定一個由shader編譯成的著色器程序。
常見的著色器主要有:????
????頂點著?器(VertexShader)????
?????段著?器 (FragmentShader)/像素著?器(PixelShader)/片元著色器/圖元著色器?
?????何著?器 (GeometryShader)?
?????曲?細(xì)分著?器(TessellationShader)
?段著?器和像素著?器只是在OpenGL和DX中的不同叫法?而已??上У氖牵钡?OpenGLES 3.0,依然只支持了頂點著?器和片段著?器這兩個最基礎(chǔ)的著?器。
OpenGL在處理shader時,和其他編譯器一樣。通過編譯、鏈接等步驟,?成了著?器程序(glProgram),著?器程序同時包含了頂點著?器和?段著?器的運算邏輯。
在OpenGL進(jìn)行繪制的時候,?先由頂點著?器對傳?的頂點數(shù)據(jù)進(jìn)行運算。再通過圖元裝配,將頂點轉(zhuǎn)換為圖元。然后進(jìn)行光柵化,將圖元這種矢量圖形,轉(zhuǎn)換為柵格化數(shù)據(jù)。最后,將柵格化數(shù)據(jù)傳入?段著?器中進(jìn)行運算。?段著?器會對柵格化數(shù)據(jù)中的每一個像素進(jìn)行運算,并決定像素的顏?。
頂點著色器(VertexShader)
一般用來處理圖形每個頂點變換,即:旋轉(zhuǎn)/平移/投影等。
頂點著色器是OpenGL中用于計算頂點屬性的程序。頂點著色器是逐個頂點運算的程序,也就是說每個頂點數(shù)據(jù)都會執(zhí)行一次頂點著色器,當(dāng)然這是并行的,并且頂點著色器運算過程中無法訪問其他頂點的數(shù)據(jù)
一般來說典型的需要計算的頂點屬性包括頂點坐標(biāo)變換、逐個頂點光照運算等等。頂點坐標(biāo)由自身坐標(biāo)系轉(zhuǎn)換到歸一化做標(biāo)記的運算,就是在這里發(fā)生的。
屬性 : 用頂點數(shù)組提供的逐頂點數(shù)據(jù);
統(tǒng)一變量和統(tǒng)一變量緩沖區(qū) : 頂點著色器使用的不變數(shù)據(jù);
采樣器 : 代表頂點著色器使用的紋理的特殊統(tǒng)一變量類型;
著色器程序 : 頂點著色器程序源代碼或者描述在操作頂點的可執(zhí)行文件。
片元著色器 (FragmentShader)
一般用來處理圖形中每個像素點顏色計算和填充
片段著色器是OpenGL中用于計算片段(像素)顏色的程序。片段著色器是逐個像素運算的程序,也就是說每個像素都會執(zhí)行一次片段著色器,當(dāng)然也是并行的。
片元著色器是一個處理片元值及其相關(guān)聯(lián)數(shù)據(jù)的可編程單元,片元著色器可執(zhí)行紋理的訪問、顏色的匯總、霧化等操作,每片元執(zhí)行一次。片元著色器替代了紋理、顏色求和、霧以及Alpha測試,這一部分是需要開發(fā)者自己開發(fā)的。
GLSL(OpenGL Shading language)
OpenGL著色語言(OpenGL Shading language)是用來在OpenGl中著色編程的語言,類似于C語言。他們是在圖形卡的GPU(Graphic Proccessor Unit圖形處理單元)上執(zhí)行的。代替了固定的渲染管線的一部分,使渲染管線中不同層次具有可編程性。比如:視圖轉(zhuǎn)換、投影轉(zhuǎn)換等。GLSL(GL Shading Language)的著色器代碼分成2個部分:Vertex Shader(頂點著色器)和Fragment(片斷著色器),有時還會有Geometry Shader(幾何著色器)。負(fù)責(zé)運行頂點著色的是頂點著色器。它可以得到當(dāng)前OpenGL 中的狀態(tài),GLSL內(nèi)置變量進(jìn)行傳遞。GLSL其使用C語言作為基礎(chǔ)高階著色語言,避免了使用匯編語言或硬件規(guī)格語言的復(fù)雜性。
光柵化(Rasterization)
官方翻譯成柵格化或者像素化。光柵化就是把頂點數(shù)據(jù)轉(zhuǎn)換為片元的過程,實際繪制或填充每個定點之間的像素行程過程。片元中的每一個元素對應(yīng)于幀緩沖區(qū)中的一個像素。該過程包含了兩部分的工作。第一部分工作:決定了窗口坐標(biāo)中哪些整型格柵區(qū)域被基本圖元占用。第二部分工作:分配一個顏色值和一個深度值到各個區(qū)域。光柵化過程產(chǎn)生的是片元。
把物體的數(shù)學(xué)描述以及與物體相關(guān)的顏色信息轉(zhuǎn)換為屏幕上用于對應(yīng)位置的像素及?于填充像素的顏色,這個過程稱為光柵化,這是一個將模擬信號轉(zhuǎn)化為離散信號的過程。
紋理
紋理可以理解為一個圖片,也就是位圖。?家在渲染圖形時需要在其編碼填充圖?,為了使得場景更加逼真.?這里使?的圖片,就是常說的紋理.但是在OpenGL,我們更加習(xí)慣叫紋理,?不是圖片。
OpenGL要求紋理的高度和寬度都必須是2的n次方大小,只有滿足這個條件,這個紋理圖片才是有效的。一般使用uv來表示紋理坐標(biāo),uv是一個二維向量(u,v),u和v的取值從0到1。我在代碼中為每個頂點數(shù)據(jù)增加了2個GLFloat來表示uv的值。
使用OpenGL函數(shù)生成紋理,除了使用GLKit生成紋理之外,還可以直接使用OpenGL生成紋理。
1、將圖片的數(shù)據(jù)以RGBA的形式導(dǎo)出;
2、使用glGenTextures生成紋理,這里生成的紋理就相當(dāng)于上面說到的self.diffuseTexture.name;
3、使用glBindTexture綁定紋理到GL_TEXTURE_2D;
4、使用glTexImage2D寫圖片數(shù)據(jù),我們的圖片數(shù)據(jù)已經(jīng)統(tǒng)一導(dǎo)出成RGBA格式了,所以顏色格式參數(shù)使用GL_RGBA。每個顏色組件參數(shù)使用GL_UNSIGNED_BYTE,就是說R,G,B,A每個數(shù)據(jù)各占一個字節(jié)的大??;
5、使用glTexParameteri設(shè)置采樣方式和重復(fù)方式,每個方式具體的效果大家可以自行修改例子觀察一下。重復(fù)方式主要用于uv超出0到1的場景;
6、glBindTexture(GL_TEXTURE_2D, 0);是為了清空GL_TEXTURE_2D綁定的數(shù)據(jù),可以把GL_TEXTURE_2D理解為一個工作臺,你處理完了你的事情需要把工作臺清理干凈。
混合(gl_blend)
在測試階段之后,如果像素依然沒有被剔除,那么像素的顏色將會和幀緩沖區(qū)中顏色附著上的顏色進(jìn)行混合,混合的算法可以通過OpenGL的函數(shù)進(jìn)行指定。但是OpenGL提供的混合算法是有限的,如果需要更加復(fù)雜的混合算法,?般可以通過像素著?器進(jìn)行實現(xiàn),當(dāng)然性能會比原生的混合算法差一些。
混合常用來繪制透明或半透明的物體。在混合中起關(guān)鍵作用的α值實際上是將源色和目標(biāo)色按給定比率進(jìn)行混合,以達(dá)到不同程度的透明。α值為0則完全透明,α值為1則完全不透明。混合操作只能在RGBA模式下進(jìn)行,顏色索引模式下無法指定α值。物體的繪制順序會影響到OpenGL的混合處理。
glEnable( GL_BLEND ); ? // 啟用混合
glDisable( GL_BLEND );? // 禁用關(guān)閉混合
矩陣變換(Transformation)
圖形想發(fā)生平移,縮放,旋轉(zhuǎn)變換。就需要使用變換矩陣。
Peakin 來源:CSDN 原文:https://blog.csdn.net/u014587123/article/details/80337627
模型變換:
????模型變換解決的是,把物體在世界坐標(biāo)系下的位置拆分成平移、縮放、旋轉(zhuǎn)的表達(dá)方式。?
視圖變換:
????視圖變換的作用可以理解為,指定一個照相機的位置和角度。
投影變換:
????投影變換是把前面在三維空間中的坐標(biāo)投影到二維屏幕坐標(biāo),但是計算結(jié)果也是一個三維坐標(biāo)(嚴(yán)格來說是四維的,還有個齊次的 1),除了屏幕的橫縱坐標(biāo)之外,另一個維度就是垂直屏幕方向上的深度坐標(biāo),就是之后可以寫入深度緩沖器的值。
視口變換:
????視口變換,這里只是一個非常簡單的 X-Y 平面上的縮放,它決定了最終渲染到屏幕上的哪一塊區(qū)域。
變換結(jié)果:
????變換后的坐標(biāo) = 視口矩陣 x 投影矩陣 x 視圖矩陣 x 模型矩陣 x 模型點坐標(biāo) 其中模型點坐標(biāo)和變換后的坐標(biāo)是 1x4 的向量,其他矩陣都是 4x4 的。 規(guī)定:OpenGL的向量為列向量,矩陣和向量采用的方式又是“矩陣X列向量”的方式,當(dāng)多個矩陣乘以向量時,應(yīng)該從右向左計算。故上式的計算順序為模型點坐標(biāo)先與模型矩陣相乘,再與視圖矩陣相乘,投影矩陣和視口矩陣,最后得到變換后的坐標(biāo)。

投影矩陣(Projection)
負(fù)責(zé)給場景增加透視;?于將3D坐標(biāo)轉(zhuǎn)換為二維屏幕坐標(biāo),實際線條也將在二維坐標(biāo)下進(jìn)行繪制。
投影矩陣P:滿足P^2=P
正交矩陣矩陣P:P'=P=P^2
超定線性方程組Ax=b通常化成解PAx=Pb,其中P是全空間到A的值域Im(A)的投影,經(jīng)等價變換可得A'Ax=A'b
在線性代數(shù)和泛函分析中,投影是從向量空間映射到自身的一種線性變換,是日常生活中“平行投影”概念的形式化和一般化。同現(xiàn)實中陽光將事物投影到地面上一樣,投影變換將整個向量空間映射到它的其中一個子空間,并且在這個子空間中是恒等變換。
渲染上屏/交換緩沖區(qū)(SwapBuffer)
常規(guī)的OpenGL程序?至少都會有兩個緩沖區(qū)。顯示在屏幕上的稱為屏幕緩沖區(qū),沒有顯示的稱為離屏緩沖區(qū)。在一個緩沖區(qū)渲染完成之后,通過將屏幕緩沖區(qū)和離屏緩沖區(qū)交換,實現(xiàn)圖像在屏幕上的顯示。
當(dāng)我們想把一個圖像渲染到窗口的時候,GPU會開辟一個渲染緩沖區(qū)。但是每一個窗口又只有一個緩沖區(qū),那么如果在繪制的過程中屏幕進(jìn)行了刷新,窗口顯示的畫面就有可能不完整。為了解決這個問題,常規(guī)的OpenGL程序至少都會有兩個緩沖區(qū)。顯示在屏幕上的稱為屏幕緩沖區(qū),沒有顯示的稱為離屏緩沖區(qū),在一個緩沖區(qū)渲染完成之后,通過將屏幕緩沖區(qū)和離屏緩沖區(qū)交換,實現(xiàn)圖像在屏幕上的顯示。在iOS中經(jīng)常遇到的離屏渲染,其實就是雙緩沖區(qū)的機制引起的。