OpenGL(Open Graphics Library)是一個跨編程語言、跨平臺的編程圖形程序接口,它將計算機的資源抽象稱爲一個個OpenGL的對象,對這些資源的操做抽象爲一個個的OpenGL指令算法
OpenGL ES(OpenGL for Embedded Systems)是 OpenGL 三維圖形 API 的子集,針對手機、PDA和遊戲主機等嵌入式設備而設計,去除了許多沒必要要和性能較低的API接口。編程
DirectX:是由不少API組成的,DirectX並非一個單純的圖形API. 最重要的是DirectX是屬於Windows上一個多媒體處理API.並不支持Windows之外的平臺,因此不是跨平臺框架. 按照性質分類,能夠分爲四大部分,顯示部分、聲音部分、輸入部分和網絡部分.數組
Metal: Apple爲遊戲開發者推出了新的平臺技術 Metal,該技術可以爲 3D 圖像提升 10 倍的渲染性能.Metal 是Apple爲了解決3D渲染而推出的框架,在2014年之前蘋果一直沿用OpenGL ES 來解決底層渲染.然後開始慢慢將自身的底層框架的依賴從OpenGL ES遷移到Metal.但其核心的處理思想仍是源於OpenGL ES.對於適應於OpenGL ES的開發者而言並無太大的改變.緩存
引言:bash
從2014年到2018年.蘋果才完成了系統內部從OpenGL ES過分到Metal.直到WWDC 2018,Apple 宣佈 iOS 12 將棄用 OpenGL / CL.微信
Apps built using OpenGL ES will continue to run in iOS 12, but Open GL ES is deprecated in iOS 12. Games and graphics-intensive apps that previously used OpenGL ES should now adopt Metal.網絡
但值得注意的是:架構
- 首先蘋果自身的系統遷移上是花費了4年時間作這樣的籌備.
- 其次在沒有推出Metal 蘋果對於OpenGL ES是高度集成且配合相應圖層和GLKit 來輔助開發者能快速使用OpenGL ES
- OpenGL ES的棄用,只是針對蘋果內部系統底層API依賴而言,並非想讓iOS開發者今後不使用OpenGLES. OpenGL ES只是角色變成第三方.畢竟它的跨平臺以及穩定,是很難讓現有的開發放棄.而這2點Metal 目前很難給到
- 最後,若是你們想要融入到項目組,而目前大多數相似百度地圖,高德地圖和音視頻處理的項目組已是很是龐大的項目了,暫時不會遷移到Metal.因此咱們若是隻會metal從實際場景中並不夠.
- 因此咱們學習會從OpenGL->OpenGL ES->Metal
OpenGL 上下文(context) 在應用程序調用任何OpenGL的指令以前,須要安排首先建立一個OpenGL的上下文。這個上下文是一個很是龐大的狀態機,保存了OpenGL中的各類狀態,這也是OpenGL指令執行的基礎。app
OpenGL的函數無論在哪一個語言中,都是相似C語言同樣的面向過程的函數,本質上都是對OpenGL上下文這個龐大的狀態機中的某個狀態或者對象進行操做,固然你得首先把這個對象設置爲當前對象。所以,經過對OpenGL指令的封裝,是能夠將OpenGL的相關調用封裝成爲一個面向對象的圖形API的。框架
因爲OpenGL上下文是一個巨大的狀態機,切換上下文每每會產生較大的開銷,可是不一樣的繪製模塊,可能須要使用徹底獨立的狀態管理。所以,能夠在應用程序中分別建立多個不一樣的上下文,在不一樣線程中使用不一樣的上下文,上下文之間共享紋理、緩衝區等資源。這樣的方案,會比反覆切換上下文,或者大量修改渲染狀態,更加合理高效的。
OpenGL 狀態機 狀態機是理論上的一種機器.這個很是難以理解.因此咱們把這個狀態機這麼理解.狀態機描述了一個對象在其生命週期內所經歷的各類狀態,狀態間的轉變,發生轉變的動因,條件及轉變中所執行的活動。或者說,狀態機是一種行爲,說明對象在其生命週期中響應事件所經歷的狀態序列以及對那些狀態事件的響應。所以具備如下特色:
類推到OpenGL 中來,能夠這麼理解:
可使用glColor函數來選擇一種顏色,之後繪製的全部物體都是這種顏色,除非再次使用glColor函數從新設定。
可使用glTexCoord函數來設置一個紋理座標,之後繪製的全部物體都是採用這種紋理座標,除非再次使用glTexCoord函數從新設置。
可使用glBlendFunc函數來指定混合功能的源因子和目標因子,之後繪製的全部物體都是採用這個源因子和目標因子,除非再次使用glBlendFunc函數從新指定。
可使用glLight*函數來指定光源的位置、顏色,之後繪製的全部物體都是採用這個光源的位置、顏色,除非再次使用glBlendFunc函數從新指定。
例如:
//獲取是否深度測試/混合
glIsEnabled(GL_DEPTH_TEST);
glIsEnabled(GL_BLEND);
//開啓深度測試/混合
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
//關閉深度測試/混合
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
複製代碼
將圖形/圖像數據轉換成3D空間圖像操做叫作渲染(Rendering).
畫圖通常是先畫好圖像的骨架,而後再往骨架裏面填充顏色,這對於OpenGL也是同樣的。頂點數據就是要畫的圖像的骨架,和現實中不一樣的是,OpenGL中的圖像都是由圖元組成。在OpenGLES中,有3種類型的圖元:點、線、三角形。那這些頂點數據最終是存儲在哪裏的呢?開發者能夠選擇設定函數指針,在調用繪製方法的時候,直接由內存傳入頂點數據,也就是說這部分數據以前是存儲在內存當中的,被稱爲頂點數組。而性能更高的作法是,提早分配一塊顯存,將頂點數據預先傳入到顯存當中。這部分的顯存,就被稱爲頂點緩衝區。 頂點指的是咱們在繪製一個圖形時,它的頂點位置數據.而這個數據能夠直接存儲在數組中或者將其緩存到GPU內存中.
在OpenGL 下渲染圖形,就會有經歷一個一個節點.而這樣的操做能夠理解管線.你們能夠想象成流水線.每一個任務相似流水線般執行.任務之間有前後順序. 管線是一個抽象的概念,之因此稱之爲管線是由於顯卡在處理數據的時候是按照一個固定的順序來的,並且嚴格按照這個順序。就像水從一根管子的一端流到另外一端,這個順序是不能打破的
在早期的OpenGL 版本,它封裝了不少種着色器程序塊內置的一段包含了光照、座標變換、裁剪等等諸多功能的固定shader程序來完成,來幫助開發者來完成圖形的渲染. 而開發者只須要傳入相應的參數,就能快速完成圖形的渲染. 相似於iOS開發會封裝不少API,而咱們只須要調用,就能夠實現功能.不須要關注底層實現原理. 可是因爲OpenGL 的使用場景很是豐富,固定管線或存儲着色器沒法完成每個業務.這時將相關部分開放成可編程.
就全面的將固定渲染管線架構變爲了可編程渲染管線。所以,OpenGL在實際調用繪製函數以前,還須要指定一個由shader編譯成的着色器程序。常見的着色器主要有頂點着色器(VertexShader),片斷着色器(FragmentShader)/像素着色器(PixelShader),幾何着色器(GeometryShader),曲面細分着色器(TessellationShader)。片斷着色器和像素着色器只是在OpenGL和DX中的不一樣叫法而已。惋惜的是,直到OpenGLES 3.0,依然只支持了頂點着色器和片斷着色器這兩個最基礎的着色器。 OpenGL在處理shader時,和其餘編譯器同樣。經過編譯、連接等步驟,生成了着色器程序(glProgram),着色器程序同時包含了頂點着色器和片斷着色器的運算邏輯。在OpenGL進行繪製的時候,首先由頂點着色器對傳入的頂點數據進行運算。再經過圖元裝配,將頂點轉換爲圖元。而後進行光柵化,將圖元這種矢量圖形,轉換爲柵格化數據。最後,將柵格化數據傳入片斷着色器中進行運算。片斷着色器會對柵格化數據中的每個像素進行運算,並決定像素的顏色
通常用來處理圖形每一個頂點變換(旋轉/平移/投影等) 頂點着色器是OpenGL中用於計算頂點屬性的程序。頂點着色器是逐頂點運算的程序,也就是說每一個頂點數據都會執行一次頂點着色器,固然這是並行的,而且頂點着色器運算過程當中沒法訪問其餘頂點的數據。 通常來講典型的須要計算的頂點屬性主要包括頂點座標變換、逐頂點光照運算等等。頂點座標由自身座標系轉換到歸一化座標系的運算,就是在這裏發生的。
通常用來處理圖形中每一個像素點顏色計算和填充 片斷着色器是OpenGL中用於計算片斷(像素)顏色的程序。片斷着色器是逐像素運算的程序,也就是說每一個像素都會執行一次片斷着色器,固然也是並行的。
OpenGL着色語言(OpenGL Shading Language)是用來在OpenGL中着色編程的語言,也即開發人員寫的短小的自定義程序,他們是在圖形卡的GPU (Graphic Processor Unit圖形處理單元)上執行的,代替了固定的渲染管線的一部分,使渲染管線中不一樣層次具備可編程性。好比:視圖轉換、投影轉換等。GLSL(GL Shading Language)的着色器代碼分紅2個部分:Vertex Shader(頂點着色器)和Fragment(片段着色器)
是把頂點數據轉換爲片元的過程,具備將圖轉化爲一個個柵格組成的圖象的做用,特色是每一個元素對應幀緩衝區中的一像素。 光柵化就是把頂點數據轉換爲片元的過程。片元中的每個元素對應於幀緩衝區中的一個像素。 光柵化實際上是一種將幾何圖元變爲二維圖像的過程。該過程包含了兩部分的工做。第一部分工做:決定窗口座標中的哪些整型柵格區域被基本圖元佔用;第二部分工做:分配一個顏色值和一個深度值到各個區域。光柵化過程產生的是片元 把物體的數學描述以及與物體相關的顏色信息轉換爲屏幕上用於對應位置的像素及用於填充像素的顏色,這個過程稱爲光柵化,這是一個將模擬信號轉化爲離散信號的過程
紋理能夠理解爲圖片. 你們在渲染圖形時須要在其編碼填充圖片,爲了使得場景更加逼真.而這裏使用的圖片,就是常說的紋理.可是在OpenGL,咱們更加習慣叫紋理,而不是圖片.
在測試階段以後,若是像素依然沒有被剔除,那麼像素的顏色將會和幀緩衝區中顏色附着上的顏色進行混合,混合的算法能夠經過OpenGL的函數進行指定。可是OpenGL提供的混合算法是有限的,若是須要更加複雜的混合算法,通常能夠經過像素着色器進行實現,固然性能會比原生的混合算法差一些。
例如圖形想發平生移,縮放,旋轉變換.就須要使用變換矩陣.
用於將3D座標轉換爲二維屏幕座標,實際線條也將在二維座標下進行繪製.
渲染緩衝區通常映射的是系統的資源好比窗口。若是將圖像直接渲染到窗口對應的渲染緩衝區,則能夠將圖像顯示到屏幕上。
可是,值得注意的是,若是每一個窗口只有一個緩衝區,那麼在繪製過程當中屏幕進行了刷新,窗口可能顯示出不完整的圖像。
爲了解決這個問題,常規的OpenGL程序至少都會有兩個緩衝區。顯示在屏幕上的稱爲屏幕緩衝區,沒有顯示的稱爲離屏緩衝區。在一個緩衝區渲染完成以後,經過將屏幕緩衝區和離屏緩衝區交換,實現圖像在屏幕上的顯示。
因爲顯示器的刷新通常是逐行進行的,所以爲了防止交換緩衝區的時候屏幕上下區域的圖像分屬於兩個不一樣的幀,所以交換通常會等待顯示器刷新完成的信號,在顯示器兩次刷新的間隔中進行交換,這個信號就被稱爲垂直同步信號,這個技術被稱爲垂直同步。
使用了雙緩衝區和垂直同步技術以後,因爲老是要等待緩衝區交換以後再進行下一幀的渲染,使得幀率沒法徹底達到硬件容許的最高水平。爲了解決這個問題,引入了三緩衝區技術,在等待垂直同步時,來回交替渲染兩個離屏的緩衝區,而垂直同步發生時,屏幕緩衝區和最近渲染完成的離屏緩衝區交換,實現充分利用硬件性能的目的。
小編在這裏給你們推薦一個優秀的iOS交流平臺,平臺裏的夥伴們都是很是優秀的iOS開發人員,咱們專一於技術的分享與技巧的交流,你們能夠在平臺上討論技術,交流學習。歡迎你們的加入(想要進入的可加微信)。 18174412518
做者:CC老師_HelloCoder 轉載連接:www.jianshu.com/p/1b09101aa…