EGL(Embedded Graphics Library)
- OpenGL ES 命令需要
渲染上下?和繪制表面才能完成圖形圖像的繪制 - 渲染上下?: 存儲相關OpenGL ES狀態(tài),是一個狀態(tài)機
- 繪制表面:?于繪制圖元的表面,需要指定渲染的緩存區(qū),例如顏?緩、深度和模板
- OpenGL ES API并沒有提供如何創(chuàng)建渲染上下文或者上下文如何連接到原生窗口系統(tǒng),EGL是Khronos 渲染API(如OpenGL ES) 和原?窗?系統(tǒng)之間的接?。
唯?支持OpenGL ES卻不支持EGL的平臺是iOS,Apple提供?己的EGL API的iOS實現(xiàn),稱為EAGL - 因為每個窗?系統(tǒng)都有不同的定義,所以EGL提供基本的不透明類型—EGLDisplay, 這 個類型封裝了所有系統(tǒng)相關性,用于和原生窗?系統(tǒng)接?
主要功能
- 和本地窗口系統(tǒng)(native windowing system)通訊
- 查詢可用的配置
- 創(chuàng)建OpenGL ES可用的“繪圖表面”(drawing surface)
- 同步不同類別的API之間的渲染,比如在OpenGL ES和OpenVG之間同步,或者在OpenGL和本地窗口的繪圖命令之間
- 管理“渲染資源”,比如紋理映射(Rendering map)
GLSL語言
- xcode中不支持GLSL語言對頂點/片元著色器的編譯和連接,因此需要在項目中創(chuàng)建兩個空文件,分別命名為shader.vsh和shaderv.fsh
- 使用vsh、fsh后綴的原因是方便區(qū)分著色器,其本質就是一個字符串(也可以使用其他后綴)
- 不建議在這兩個文件中直接使用NSString,因為這樣子會使代碼結構不清晰,且不易讀
- 不建議在這兩個文件中加中文注釋,因為可能會報奇怪的錯誤。由于在xcode中書寫GLSL,完全是純手寫,沒有任何提示,排查問題不好排查
數(shù)據(jù)類型及相關API
向量數(shù)據(jù)類型
常用的是vec2、vec3、vec4,默認是浮點類型
| 類型 | 描述 |
|---|---|
| vec2, vec3, vec4 | 2分量、3分量、4分量浮點向量 |
| ivec2, ivec3, ivec4 | 2分量、3分量、4分量整型向量 |
| uvec2, uvec3, uvec4 | 2分量、3分量、4分量無符號整型向量 |
| bvec2, bvec3, bvec4 | 2分量、3分量、4分量bool型向量 |
矩陣數(shù)據(jù)類型
最常用的是mat3、mat4
| 類型(mat列×行) | 描述 |
|---|---|
| mat2,mat2x2 | 兩?兩列 |
| mat3,mat3x3 | 三行三列 |
| mat4,mat4x4 | 四行四列 |
| mat2x3 | 三行兩列 |
| mat2x4 | 四行兩列 |
| mat3x2 | 兩行三列 |
| mat3x4 | 四行三列 |
| mat4x2 | 兩行四列 |
| mat4x3 | 三行四列 |
變量存儲限定符
常用varying、attribute、uniform
- varying 修飾符:當需要將頂點著色器的數(shù)據(jù)傳遞到片元著色器時,兩個著色器中一模一樣的紋理坐標變量就需要它來修飾
- attribute 修飾符:數(shù)據(jù)只能從客戶端中傳遞到頂點著色器,且只能在頂點著色器中使用
- 修飾的數(shù)據(jù):頂點、紋理、顏色、法線等
- API通常以
glVertex...開頭,例如glVertexAttribPointer - 其中的紋理坐標,需要頂點著色器間接傳遞到片元著色器,需要在頂點與片元著色器中定義一個一模一樣的紋理坐標,通過這個變量將紋理坐標數(shù)據(jù)間接傳遞到片元著色器,
varying lowp vec2 varyTextCoord; - 頂點著色器計算之后的頂點結果需要賦值給GLSL的內(nèi)建變量
gl_Position
attribute vec4 position;
attribute vec2 textCoordinate;
varying lowp vec2 varyTextCoord;
void main()
{
varyTextCoord = textCoordinate;
gl_Position = position;
}
- uniform 修飾符:從app代碼傳遞到vertex、fragment中所用的變量
- 在vertex,fragment中一般將uniform當成常量
- uniform可以傳的數(shù)據(jù):視圖矩陣、投影矩陣、投影視圖矩陣
- API通常以·glUniform...·開頭
- 片元著色器中最終顏色,即拿到紋理對應坐標下的紋素。紋素是紋理對應像素點的顏色值,需要通過內(nèi)建函數(shù)
texture2D(紋理,紋理坐標)計算,將最終返回的顏色值賦值給內(nèi)建變量gl_FragColor
//需要定義精度,否則可能會報錯
precsion highp float;
//紋理坐標 必須與頂點著色器中一模一樣,通過這個參數(shù)獲取傳遞過來的值
varying lowp vec2 varyTextCoord;
//紋理
uniform sampler2D colorMap;
void main(){
//1、拿到紋理對應坐標下的紋素。紋素是紋理對應像素點的顏色值
lowp vec4 temp = texture2D(colorMap, varyTextCoord);
//2、非常重要且必須的內(nèi)建變量:gl_FragColor
gl_FragColor = temp;
}
| 限定符 | 描述 |
|---|---|
| <none> | 只是普通的本地變量,外部不見,外部不可訪問 |
| const | ?個編譯常量,或者說是?個對函數(shù)來說為只讀的參數(shù) |
| in/varying | 從以前階段傳遞過來的變量 |
| in/varying centroid | ?個從以前的階段傳遞過來的變量,使?質?插值 |
| out/attribute | 傳遞到下?個處理階段或者在?個函數(shù)中指定?個返回值 |
| out/attribute centroid | 傳遞到下?個處理階段,質心插值 |
| uniform | ?個從客戶端代碼傳遞過來的變量,在頂點之間不做改變 |
OpenGL ES 錯誤處理
如果不正確使用OpenGL ES 命令,應用程序就會產(chǎn)生一個錯誤編碼,且會被記錄,可以用glGetError查詢,一旦查詢到錯誤代碼,當前的錯誤代碼就會復位為GL_NO_ERROR
| 錯誤代碼 | 描述 |
|---|---|
| GL_NO_ERROR | 從上?次調(diào)?glGetError 以來沒有生成任何錯誤 |
| GL_INVALID_ENUM | GLenum 參數(shù)超出范圍,忽略生成錯誤命令 |
| GL_INVALID_VALUE | 數(shù)值型 參數(shù)超出范圍,忽略生成錯誤命令 |
| GL_INVALID_OPERATION | 特定命令在當前OpenGL ES 狀態(tài)?法執(zhí)? |
| GL_OUT_OF_MEMORY | 內(nèi)存不足時執(zhí)?該命令,如果遇到這個錯誤,除?當前錯誤代碼,否則OpenGL ES 管線的 狀態(tài)被認為未定義 |
OpenGL ES 自定義著色器常用API
自定義著色器一般有以下步驟:
- 創(chuàng)建頂點著色器/片元著色器 --
glCreateShader - 指定shader的source --
glShaderSource - 編譯shader --
glCompileShader
以下是創(chuàng)建與編譯一個著色器的相關API

著色器API.png
自定義程序
自定義程序一般有以下步驟:
- 創(chuàng)建一個程序對象 --
glCreateProgram - 著色器與程序連接/附著 --
glAttachShader - 鏈接程序 --
glLinkProgram - 使用程序 --
glUseProgram
以下是創(chuàng)建與鏈接程序的相關API

創(chuàng)建與鏈接程序的相關API.png