一、簡介
在之前,我寫了幾篇學習 OpenGL 的文章,大家有興趣的可以去看一下,在學習了 OpenGL 的基礎上,現在再來學習一下它的簡化版本—— OpenGL ES。
OpenGL ES(OpenGL for Embedded Systems)是以手持和嵌?式設備為?標的?級 3D 圖形應?程序編程接口(API)。 OpenGL ES 是目前智能手機中占據統治地位的圖形 API。支持的平臺包括:iOS,Andriod,BlackBerry,bada,Linux 和 Windows,它還是基于瀏覽器的 3D 圖形 Web 標準WebGL 的基礎。
OpenGL ES 是 OpenGL 的簡化版本,它消除了冗余功能,提供了一個既易于學習又更易于在移動圖形硬件中實現的庫。OpenGL ES允許應?程序利?底層圖形處理器的強大功能。iOS 設備上的 GPU 可以執行復雜的 2D 和 3D 繪圖,以及最終圖像中每個像素的復雜著色計算。
簡單的來說,OpenGL ES 和 OpenGL 學習起來大致一樣,有很多重復的知識點。整個渲染管線流程如上圖,還是以前那一套,具體流程可以看我之前寫過的 《OpenGL基礎渲染》。所以這篇文章就不再贅述渲染流程,而是著重介紹 OpenGL ES 中幾個重要的步驟。
可編程管線中,我們只能操作 頂點著色器 和 片元著色器。
二、關鍵步驟介紹
1、頂點著色器
1)頂點著色器的輸入輸出:
頂點著色器 實現了頂點操作的通用可編程方法。
頂點著色器 的 輸入 包括:
- 著色器程序 —— 描述頂點上執?操作的頂點著色器程序源代碼(GLSL代碼)或者可執行?文件。
- 頂點著色器輸入(或者屬性Attributes)—— 用頂點數組提供的每個頂點的數據。
- 統一變量(uniform)—— 頂點(或者片段)著色器使用的不變數據(例如旋轉矩陣)。
- 采樣器 —— 代表頂點著色器使用紋理的特殊統一變量類型。
圖形表述如下圖所示:
2)頂點著色器的業務:
1、通過矩陣變換位置
2、計算光照公式生成逐頂點顏色
3、生成或變換紋理坐標
此外,因為頂點著色器由應用程序規定,所以它可以用于執行自定義計算,實施新的變換、照明或者較傳統的固定功能管線所不允許的基于頂點的效果。
3)GLSL 代碼的簡單認識:
格式:
通道修飾符
類型
變量名
attribute vec4 position; attribute vec2 textCoordinate; uniform mat4 rotateMatrix;
- attribute 和 uniform 對應
通道修飾符
,
分別是 attribute屬性通道 和 uniform 通道。- vec4、vec2 和 mat4 對應
類型
,
vec4 代表 4 維向量,
vec2 代表 2 維向量,
mat4 代表 4 行 4 列的矩陣類型。- position 和 textCoordinate 對應
變量名
,可以隨便起。varying lowp vec2 varyTextCoord;
varying 代表的也是一種通道,
lowp 是一個精度,低精度、高精度等,可以不寫。
- 這里 position 聲明的是 頂點坐標,
textCoordinate 聲明的是 紋理坐標。
rotateMatrix 聲明的是個 旋轉矩陣。
4)頂點著色器的代碼案例:
attribute vec4 position;
attribute vec2 textCoordinate;
uniform mat4 rotateMatrix;
varying lowp vec2 varyTextCoord;
void main()
{
// 把textCoordinate交給varyTextCoord,就可以把紋理坐標傳遞到片元著色器里面去。
varyTextCoord = textCoordinate;
vec4 vPos = position;
vPos = vPos * rotateMatrix;// 讓每一個頂點都和旋轉矩陣相乘
gl_Position = vPos;// gl_Position是一個內建變量,是vec4類型的,必須給它賦值。
}
GPU 來執行上述代碼,有幾個頂點就會執行其次,GPU 是并行的,所以會并行把所有頂點都執行了。
2、圖元裝配
頂點著色器之后,OpenGL ES 3.0 圖形管線的下一階段是 圖元裝配。
圖元(Primitive):是三角形、直線或者點精靈等幾何對象。圖元裝配:將頂點數據計算組合成一個個圖元,在這個階段會執行裁剪、透視分割和 Viewport 變換操作。
在這之后將進? 光柵化 階段。
3、光柵化
在此階段繪制對應的圖元(點精靈、直線或者三角形)。光柵化是將圖元轉化為一組二維片段的過程,然后這些片段由片元著色器處理。這些二維片段代表著可在屏幕上繪制的像素。4、片元(片段)著色器
1)片元著色器的輸入輸出:
片元/?段著色器 的 輸入 包括:
- 著色器程序 —— 描述?段上執?操作的片元著?器程序源代碼/可執行?件。
- 輸入變量—— 光柵化單元用插值為每個片段生成的頂點著?器輸出。
- 統一變量(uniform)—— 頂點(或者片段)著色器使用的不變數據。
- 采樣器 —— 代表?元著色器使?紋理的特殊統一變量類型。
圖形表述如下圖所示:
2)片元著色器的業務:
1、計算顏色
2、獲取紋理值
3、往像素點中填充顏色值【紋理值/顏色值】
總結:它可以用于圖片/視頻/圖形中每個像素的顏色填充(比如給視頻添加濾鏡,實際上就是將視頻中每個圖片的像素點顏色填充進行修改)。
3)片元著色器的代碼案例:
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
void main()
{
// texture2D(紋理采樣器, 紋理坐標); 為了取得紋素(紋理對應坐標上的顏色值),比如取到了一個rgba四維變量
gl_FragColor = texture2D(colorMap, varyTextCoord);
}
頂點著色器 里的 varying lowp vec2 varyTextCoord;
和 片元著色器 里的 varying lowp vec2 varyTextCoord;
必須定義的一模一樣才行,包括通道、精度、類型和變量名都要一致,這樣才能從頂點著色器傳進來。
uniform sampler2D colorMap 是由 uniform 通道傳進來的紋理采樣器,通過它可以拿到對應的紋理。
5、逐片段操作
片元著色器之后,下一階段就是 逐片段操作。
- 像素歸屬測試:這個測試確定幀緩存區中位置 (Xw, Yw) 的像素目前是不是歸 OpenGL ES 所有。例如,如果?個顯示 OpenGL ES 幀緩存區窗口的窗口被另外一個窗口所遮蔽,則窗?系統可以確定被遮蔽的像素不屬于 OpenGL ES 上下文。從?完全不顯示這些像素。雖然像素歸屬測試是 OpenGL ES 的?部分,但它不由開發人員控制,?是在 OpenGL ES 內部進行。
- 裁剪測試:裁剪測試確定 (Xw, Yw) 是否位于作為 OpenGL ES 狀態的一部分的裁剪矩形范圍內。如果該?段位于裁剪區域之外,則被拋棄。
- 深度測試:輸?片段的深度值比較,確定?段是否應該被拒絕。
- 混合:混合將新生成的?段顏?值與保存在幀緩沖區 (Xw, Yw) 位置的顏?值組合起來。
- 抖動:抖動可用于最?化,因為使用有限精度在幀緩存區中保存顏色?產生的偽像。
6、EGL (Embedded Graphics Library )
OpenGL ES 命令需要 渲染上下文 和 繪制表面 才能完成圖形圖像的繪制。
- 渲染上下文:存儲相關 OpenGL ES 狀態。
- 繪制表?:是?于繪制圖元的表面,它指定渲染所需要的緩存區類型,例如顏色緩沖區、深度緩沖區和模板緩沖區。
OpenGL ES API 并沒有提供如何創建渲染上下文或者上下文如何連接到原?窗?系統。EGL 是 Khronos 渲染 API(如OpenGL ES)和原生窗口系統之間的接口。唯一?持 OpenGL ES 卻不?持 EGL 的平臺是 iOS。Apple 提供自己的 EGL API 的 iOS 實現,稱為 EAGL。
因為每個窗?系統都有不同的定義,所以 EGL 提供基本的不透明類型—EGLDisplay,這個類型封裝了所有統相關性,?于和原?生窗?系統接口。
至此,我們完成了 OpenGL ES 的初探(上)。后面我還會繼續分享深入學習 OpenGL ES 的學習成果給大家,點擊進入
《OpenGL ES初探(下)—— GLKit》
以上的總結參考了并部分摘抄了以下文章,非常感謝以下作者的分享!:
《OPENGL ES 3.0編程指南 原書第2版》
轉載請備注原文出處,不得用于商業傳播——凡幾多