OpenGL ES GLSL與自定義著色器API

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
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容