OpenGL ES GLSL語言
EGL(Embedded Graphics Library)
-
OpenGL ES
命令需要渲染上下?
和繪制表面
才能完成圖形圖像的繪制 - 渲染上下?: 存儲(chǔ)相關(guān)
OpenGL ES
狀態(tài)唬复,是一個(gè)狀態(tài)機(jī) - 繪制表面:?于繪制圖元的表面,需要指定渲染的緩存區(qū),例如顏?緩忠怖、深度和模板
-
OpenGL ES API
并沒有提供如何創(chuàng)建渲染上下文或者上下文如何連接到原生窗口系 統(tǒng).EGL
是Khronos
渲染API
(如OpenGL ES
) 和原?窗?系統(tǒng)之間的接?. 唯?支持OpenGL ES
卻不支持EGL
的平臺(tái)是iOS
.Apple
提供?己的EGL API
的iOS
實(shí)現(xiàn),稱為EAGL
- 因?yàn)槊總€(gè)窗?系統(tǒng)都有不同的定義,所以
EGL
提供基本的不透明類型—EGLDisplay
, 這 個(gè)類型封裝了所有系統(tǒng)相關(guān)性,用于和原生窗?系統(tǒng)接?
主要功能
- 和本地窗口系統(tǒng)(
native windowing system
)通訊 - 查詢可用的配置
- 創(chuàng)建
OpenGL ES
可用的繪圖表面
(drawing surface
) - 同步不同類別的
API
之間的渲染,比如在OpenGL ES
和OpenVG
之間同步灰伟,或者在OpenGL
和本地窗口的繪圖命令之間 - 管理
渲染資源
案腺,比如紋理映射(Rendering map
)
GLSL語言
xcode
中不支持GLSL
語言對(duì)頂點(diǎn)/片元著色器的編譯和連接效扫,因此需要在項(xiàng)目中創(chuàng)建兩個(gè)空文件看幼,分別命名為shader.vsh
和shaderv.fsh
- 使用
vsh展懈、fsh
后綴的原因是方便區(qū)分著色器销睁,其本質(zhì)就是一個(gè)字符串- 是否可以直接使用
NSString?
并不建議這樣做存崖,因?yàn)榇a結(jié)構(gòu)不清晰冻记,不易讀- 這兩個(gè)文件中是否可以加中文注釋?不建議加中文注釋来惧,會(huì)報(bào)奇怪的錯(cuò)誤冗栗,由于在
xcode
中書寫GLSL
,完全是純手寫供搀,沒有任何提示隅居,排查問題不好排查
類型及API的總結(jié)
向量數(shù)據(jù)類型
常用的vec2、vec3葛虐、vec4
胎源,默認(rèn)是浮點(diǎn)類型
vec2,vec3,vec4
2分量、3分量挡闰、4分量浮點(diǎn)向量
ivec2,ivec3,ivec4
2分量乒融、3分量掰盘、4分量整型向量
uvec2,uvec3,uvec4
2分量、3分量赞季、4分量無符號(hào)整型向量
bvec2,bvec3,bvec4
2分量愧捕、3分量、4分量bool型向量
矩陣數(shù)據(jù)類型
mat2,mat2x2
兩?兩列
mat3,mat3x3
三行三列
mat4,mat4x4
四行四列
mat2x3
三行兩列
mat2x4
四行兩列
mat3x2
兩行三列
mat3x4
四行三列
mat4x2
兩行四列
mat4x3
三行四列
變量存儲(chǔ)限定符
常用varying申钩、attribute次绘、uniform
-
varying
修飾符:當(dāng)需要將頂點(diǎn)著色器的數(shù)據(jù)傳遞到片元著色器時(shí),兩個(gè)著色器中一模一樣的紋理坐標(biāo)變量就需要它來修飾 -
attribute
:數(shù)據(jù)只能從客戶端中傳遞到頂點(diǎn)著色器撒遣,且只能在頂點(diǎn)著色器中使用- 修飾的數(shù)據(jù):頂點(diǎn)邮偎、紋理、顏色义黎、法線等
- API通常以
glVertex...
開頭禾进,例如glVertexAttribPointer
- 其中的紋理坐標(biāo),需要頂點(diǎn)著色器間接傳遞到片元著色器廉涕,需要在頂點(diǎn)與片元著色器中定義一個(gè)一模一樣的紋理坐標(biāo)泻云,通過這個(gè)變量將紋理坐標(biāo)數(shù)據(jù)間接傳遞到片元著色器,
varying lowp vec2 varyTextCoord
; - 頂點(diǎn)著色器計(jì)算之后的頂點(diǎn)結(jié)果需要賦值給
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
當(dāng)成常量 -
uniform
可以傳的數(shù)據(jù):視圖矩陣、投影矩陣层释、投影視圖矩陣 -
API
通常以glUniform...
開頭 - 片元著色器中最終顏色婆瓜,即拿到紋理對(duì)應(yīng)坐標(biāo)下的紋素。紋素是紋理對(duì)應(yīng)像素點(diǎn)的顏色值贡羔,需要通過內(nèi)建函數(shù)
texture2D
(紋理廉白,紋理坐標(biāo))計(jì)算,將最終返回的顏色值賦值給內(nèi)建變量gl_FragColor
- 在
//需要定義精度治力,否則可能會(huì)報(bào)錯(cuò)
precsion highp float;
//紋理坐標(biāo) 必須與頂點(diǎn)著色器中一模一樣,通過這個(gè)參數(shù)獲取傳遞過來的值
varying lowp vec2 varyTextCoord;
//紋理
uniform sampler2D colorMap;
void main(){
//1蒙秒、拿到紋理對(duì)應(yīng)坐標(biāo)下的紋素。紋素是紋理對(duì)應(yīng)像素點(diǎn)的顏色值
lowp vec4 temp = texture2D(colorMap, varyTextCoord);
//2宵统、非常重要且必須的內(nèi)建變量:gl_FragColor
gl_FragColor = temp晕讲;
}
<none>
只是普通的本地變量,外部不見马澈,外部不可訪問
const
?個(gè)編譯常量瓢省,或者說是?個(gè)對(duì)函數(shù)來說為只讀的參數(shù)
in/varying
從以前階段傳遞過來的變量
in/varying centroid
?個(gè)從以前的階段傳遞過來的變量,使?質(zhì)?插值
out/attribute
傳遞到下?個(gè)處理階段或者在?個(gè)函數(shù)中指定?個(gè)返回值
out/attribute centroid
傳遞到下?個(gè)處理階段痊班,質(zhì)心插值
uniform
?個(gè)從客戶端代碼傳遞過來的變量勤婚,在頂點(diǎn)之間不做改變
OpenGL ES 錯(cuò)誤處理
如果不正確使用OpenGL ES
命令,應(yīng)用程序就會(huì)產(chǎn)生一個(gè)錯(cuò)誤編碼涤伐,且會(huì)被記錄馒胆,可以用glGetError
查詢缨称,一旦查詢到錯(cuò)誤代碼,當(dāng)前的錯(cuò)誤代碼就會(huì)復(fù)位為GL_NO_ERROR
GL_NO_ERROR
從上?次調(diào)?glGetError
以來沒有生成任何錯(cuò)誤
GL_INVALID_ENUM
GLenum
參數(shù)超出范圍,忽略生成錯(cuò)誤命令
GL_INVALID_VALUE
數(shù)值型 參數(shù)超出范圍,忽略生成錯(cuò)誤命令
GL_INVALID_OPERATION
特定命令在當(dāng)前OpenGL ES
狀態(tài)?法執(zhí)?
GL_OUT_OF_MEMORY
內(nèi)存不足時(shí)執(zhí)?該命令,如果遇到這個(gè)錯(cuò)誤,除?當(dāng)前錯(cuò)誤代碼,否則OpenGL ES
管線的 狀態(tài)被認(rèn)為未定義
OpenGL ES 自定義著色器常用API
自定義著色器
自定義著色器一般有以下步驟:
- 創(chuàng)建頂點(diǎn)著色器/片元著色器 --
glCreateShader
- 指定
shader
的source
--glShaderSource
- 編譯
shader
--glCompileShader
創(chuàng)建與編譯一個(gè)著色器的相關(guān)API
自定義程序
自定義程序一般有以下步驟:
- 創(chuàng)建一個(gè)程序?qū)ο?--
glCreateProgram
- 著色器與程序連接/附著 --
glAttachShader
- 鏈接程序 --
glLinkProgram
- 使用程序 --
glUseProgram
創(chuàng)建與鏈接程序的相關(guān)API
著色器與程序的 編譯 & 鏈接
- 需要?jiǎng)?chuàng)建2個(gè)基本對(duì)象才能使用著色器進(jìn)行傳染:著色器對(duì)象和程序?qū)ο?/li>
- 獲取鏈接后著色器對(duì)象一般的編譯&鏈接分為6步:
- 創(chuàng)建一個(gè)頂點(diǎn)著色器對(duì)象和一個(gè)片元著色器對(duì)象
- 將源代碼鏈接到每個(gè)著色器對(duì)象
- 編譯著色器對(duì)象
- 創(chuàng)建一個(gè)程序?qū)ο?/li>
- 將編譯后的著色器對(duì)象連接到程序?qū)ο?/li>
- 鏈接程序?qū)ο?/li>