簡單來說就是實現圖形的底層渲染
創(chuàng)新互聯公司專注于中大型企業(yè)的成都做網站、網站建設和網站改版、網站營銷服務,追求商業(yè)策劃與數據分析、創(chuàng)意藝術與技術開發(fā)的融合,累計客戶上1000家,服務滿意度達97%。幫助廣大客戶順利對接上互聯網浪潮,準確優(yōu)選出符合自己需要的互聯網運用,我們將一直專注成都品牌網站建設和互聯網程序開發(fā),在前進的路上,與客戶一起成長!
A. 比如在游戲開發(fā)中,對于游戲場景/游戲人物的渲染
B. 比如在音視頻開發(fā)中,對于視頻解碼后的數據渲染
C. 比如在地圖引擎,對于地圖上的數據渲染
D. 比如在動畫中,實現動畫的繪制
E. 比如在視頻處理中,對于視頻加上濾鏡效果
OpenGL/OpenGL ES/Metal 在任何項目中解決問題的本質就是利用 GPU 芯片來高效渲染圖形圖像。
圖形 API 是 ios 開發(fā)者唯一接近 GPU 的方式。
OpenGL 階段:
OpenGL ES 階段:
Metal 階段:
固定管線/存儲著?器
頂點數據是由CPU/GPU來處理?
頂點緩存區(qū):區(qū)域(不在內存!-顯卡顯存中。)
片元著色器
像素著色器
片元函數
GPUImage
[-1,1]標準化設備坐標系(NDC)
物體/世界/照相機空間-右手系
規(guī)范化設備坐標:左手系。
x,y,z = 0,1,2
注意OpenGL中坐標系 OpenGL中的物體,世界,照相機坐標系都屬于右手坐標系,而規(guī)范化設備坐標系(NDC)屬于左手坐標系。籠統(tǒng)的說OpenGL使用右手坐標系是不合適的
OpenGL希望每次頂點著色后,我們的可見頂點都為標準化設備坐標系 (Normalized Device Coordinate, NDC)。也就是說每個頂點的x,y,z都應該在-1到1之間,超出這個范圍的頂點將是不可見的。
通常情況下我們會自己設定一個坐標系范圍,之后再在頂點著色器中將這些坐標系變換為標準化設備坐標,然后這些標準化設備坐標傳入光柵器(Rasterizer),將他們變換為屏幕上的二維坐標和像素。
將坐標變換為標準化設備坐標,接著再轉化為屏幕坐標的過程通常是分布進行的,也是類似于流水線那樣。在流水線中,物體的頂點在最終轉化為屏幕坐標之前還會被變換到多個坐標系系統(tǒng)(Coordinate System)。將物體的坐標變到幾個過渡坐標系(Intermediate Coordinate System)的優(yōu)點在于 在這些特定的坐標系統(tǒng)中,一些操作或運算更加方便和容易,這一點很快就變得明顯。對我們來說比較重要的總共有5個不同的坐標系統(tǒng)。
這是一個頂點在最終被轉化為片段之前需要經歷的所有不同的狀態(tài)。為了將坐標從一個坐標系變換到另一個坐標系,我們需要用到幾個變換矩陣,最重要的幾個分別是 模型(Model)、觀察(View)、投影(Projection)三個矩陣。
物體頂點的起始坐標在局部空間(Local Space),這里稱為局部坐標(Local Coordinate),他在之后在變成世界坐標(World Coordinate),觀察坐標(View Coordinate),裁剪坐標(Clip Coordinate),并最后轉為屏幕坐標(Screen Coordinate)
的形式結束。
物體坐標系: 每個物體都有他獨立的坐標系,當物理移動或者改變方向時。該物體相關聯的坐標系將隨之移動或改變方向。
物體坐標系是以物體本身而言,比如,我先向你發(fā)指令,”向前走一步“,是向你的物體坐標系發(fā)指令。我并不知道你會往哪個絕對的方向移動。比如說,當你開車的時候,有人會說向左轉,有人會說向東。但是,向左轉是物體坐標系的概念,而向東則是世界坐標系概念。
在某種情況下,我們可以理解物體坐標系為模型坐標系。因為模型頂點的坐標都是在模型坐標系中描述的。
照相機坐標系: 照相機坐標系是和觀察者密切相關的坐標系。照相機坐標系和屏幕坐標系相似,差別在于照相機坐標系處于3D空間中,而屏幕坐標系在2D平面里。
為什么要引入慣性坐標系? 因為物體坐標系轉換到慣性坐標系只需要旋轉,從慣性坐標系轉換到世界坐標系只需要平移。
OpenGL最終的渲染設備是2D的,我們需要將3D表示的場景轉換為最終的2D形式,前面使用模型變換和視覺變換將物體坐標轉到照相機坐標系后,需要進行投影變換,將坐標從照相機坐標系轉換為裁剪坐標系,經過透視除法后,變換到規(guī)范化設備坐標系(NDC),最后進行視口變換后,3D坐標才變換到屏幕上的2D坐標,這個過程入下圖:
在上面的圖中, 注意,OpenGL只定義了裁剪坐標系、規(guī)范化設備坐標系、屏幕坐標系,而局部坐標系、世界坐標系、照相機坐標系都是為了方便用戶設計而自定義的坐標系,他們的關系如下圖:
OpenGL 然后對裁剪坐標執(zhí)行透視除法從而將他們變換到標準化設備坐標。 OpenGL 會使用glViewPort內部的參數來將標準化設備坐標映射到屏幕坐標,每個坐標關聯一個屏幕上的點。這個過程稱為視口變換
局部坐標系(模型坐標系)是為了方便構造模型而設立的坐標系,建立模型時我們無需關心最終對象顯示在屏幕那個位置。
模型變換的主要目的是通過變換使得用頂點屬性定義或者3d建模軟件構造的模型,能夠按照需要,通過縮小、平移等操作放置到場景中合適的位置, 通過模型變換后,物體放置在一個全局的世界坐標系中,世界坐標系是所有物體交互的一個公共坐標系
視變換是為了方便觀察場景中物體而建立的坐標系,在這個坐標系中相機是個假設的概念,是為了便于計算而引入的。相機坐標系中的坐標,就是從相機的角度來解釋世界坐標系中的位置
OpenGL中相機始終位于原點,指向 -Z軸,而以相反的方式來調整場景中物體,從而達到相同的觀察效果。例如要觀察-Z軸方向的一個立方體的右側面,可以有兩種方式:
GLShaderManager的初始化
GLShaderManager shaderManager;
shaderManager.InitializeStockShaders();
??作為一個一個iOS底層開發(fā)小白,一直以來對于底層原理,都是一知半解的狀態(tài),希望從此時記錄自己學習底層知識的過程,也希望對其他開發(fā)中可以有一個好的幫助,因為自己看其他人的博客時候,大多數作者都是基于自己認知的前提下,記錄自己的知識,在我看來對于入門的人來說,非?;逎y懂,所以希望自己的文章,可以更加幫助其他人循序漸進的了解更多關于 iOS 的知識。文章也會盡量一步步的探索更多業(yè)務開發(fā)之外的東西,對于任何方面的技能,都可以友善的幫助后來的開發(fā)者。文章中有任何錯誤,不恰當的地方,歡迎隨時指正,多多交流才可以共同進步。想要學習 OpenGL 首先需要了解 OpenGL/OpenGL ES/Metal 三者之間的聯系:
??通俗來講就是, Apple 作為大廠,肯定要發(fā)展自己的底層渲染技術,所以推出了 Metal ,在推出 Metal 之前,蘋果的底層渲染也是基于 OpenGL/OpenGL ES 的,在 iOS 12.0以后,蘋果摒棄了 OpenGL 的相關 API ,使用 Metal 作為自己的渲染技術,但是 OpenGL 相關的 API 依然可以使用,因為在 Metal 之前,蘋果提供了非常豐富的關于使用 OpenGL 相關 API ,類似于蘋果推出了 swift ,但是 OC 依然是自己主流語言一樣。了解了相關的背景,我們接下來要知道圖形 API 究竟是用來解決什么樣的問題存在的。
?? OpenGL/OpenGL ES/Metal 在任何項目中解決問題的本質就是利用 GPU 芯片來高效的渲染圖形圖像。圖形 API 是 iOS 開發(fā)者唯一接近 GPU 的方式。想要了解 OpenGL 就要先學習關于 OpenGL 的專業(yè)名詞,了解了這些,才可以對以后的學習,有更加深刻的認識。
??狀態(tài)機在 OpenGL 可以這么理解, OpenGL 可以記錄自己的狀態(tài)(當前所使用的顏色、是否開啟了混合功能等),可以接輸入(當調用 OpenGL 函數的時候,實際上可以看成 OpenGL 在接受我們的輸入),如我們調用 glColor3f ,則 OpenGL 接收到這個輸入后會修改自己的“當前顏色”這個狀態(tài), OpenGL 可以進入停止狀態(tài),不再接收輸入。在程序退出前, OpenGL 總會先停止工作;
??這里有一個 iOS 中很經常聽到的概念, 離屏渲染 ,很多人知道離屏渲染會對 APP 的性能造成較大的開銷,但是卻不知道原理是什么,相信大家了解了上面關于 OpenGL 關于交換緩沖區(qū)的概念后,有了一個更清晰的認識,即: Off-Screen Rendering 是需要開辟新的緩沖區(qū)的,不停地切換上下文的環(huán)境則是對性能的很大的消耗,所以在 iOS 開發(fā)中,我們應當盡量的避免離屏渲染。
??在學習 OpenGL 的過程中,直接非常直觀的掌握并理解這些概念并不是一件容易的事,但是至少需要在入門階段,大致的了解這些概念的意思,然后通過后續(xù)的學習,慢慢的鞏固前面學到的知識,溫故而知新,一步步的打開關于 iOS 底層渲染知識的大門,學習的越來越深入,慢慢的回過頭看以前的知識點的時候,就會豁然開朗了。
??希望能一步步的記錄自己學習的過程,慢慢進步,慢慢成長,文章中有任何錯誤的地方,歡迎指正。希望能多多交流,共同進步。
無論是OpenGL 還是 OpenGL ES 或者 Metal ,本質上還是利用GPU來進行高效的渲染圖形圖像。
換句話說圖形API,是我們iOS開發(fā)者唯一接近GPU的方式。
首先,“狀態(tài)機”這個東西是什么,學過編譯原理的同學,一定聽過或了解這三個字。 狀態(tài)機是有限狀態(tài)自動機的簡稱,是現實事物運行規(guī)則抽象而成的一個數學模型。
如果說下圖“自動門”是個狀態(tài)機,他 記憶 了open和close狀態(tài),知道自己處在不同狀態(tài)時,下一步要干什么,是“開門”還是“關門”。 當在close狀態(tài)時,你 輸入 一個開門的信號,他就會切換成open狀態(tài)
狀態(tài)機的特點:
回到 OpenGL 狀態(tài)機:
既然有了 Metal 我們是否還有學習 OpenGL ES 的必要呢.我個人認為暫時還是有必要的.OpenGL /OpenGL ES/ Metal 在任何項目中解決問題的本質就是利用GPU芯片來?效渲染圖形圖像.所以它們底層的原理相近,首先了解OpenGL之后再去了解Metal會更加容易, 其二OpenGL是跨平臺的框架.保不齊以后會在其他的地方用到,所謂技多不壓身.畢竟不可能保證一直都做蘋果開發(fā)吧.
理論枯燥且乏味, 但是我們聯想一下flutter開發(fā)中用到的context, iOS開發(fā)中CoreGraphics里也有用到context. 是不是此時心中就有了一定的答案.我個人理解其設計模式大同小異. 顧名思義我們能夠通過context拿到很多必要的狀態(tài)和數據.
比如需要顯示一個正方形, 則需要兩個正等邊三角形圖元來完成
為了讀取效率起見, 提前分配一塊顯存, 將頂點數組存放在顯存中. 這部分顯存就叫做 頂點緩沖區(qū)
OpenGL渲染的過程中會經歷很多節(jié)點. 這些節(jié)點串起來就是管線.
常見的著?器主要有: 頂點著?器(VertexShader) , ?段著?器(FragmentShader) , 幾何著?(GeometryShader) , 曲?細分著?器(TessellationShader)
OpenGL ES 中只?持 頂點著?器 和 片段著?器 .
光柵化就是把頂點數據轉換為片元的過程。片元中的每一個元素對應于幀緩沖區(qū)中的一個像素。
如果把渲染比作是畫畫, 那么頂點著色器操作相當與確定畫的內容的框架. 而之后往框架里填充內容的過程就是光柵化.
填充好內容之后就是片元著色器操作像素點填充顏色等操作
這里附上一張流程圖:
紋理可以理解為圖?。 在渲染圖形時需要在頂點圍成的區(qū)域中填充圖?,使得場景更加逼真。?這?使?的圖?,就是常說的紋理。只是在OpenGL,我們更加習慣叫紋理,?不是圖?。