著色器進(jìn)行渲染
著色器對象和程序?qū)ο?/i>。
著色器對象和程序?qū)ο缶秃帽染幾g器和鏈接對象,著色器對象是包含單個著色器的對象,著色器對象被編譯為一個目標(biāo)形式 (類似.o .obj文件),編譯之后著色器對戲那個可以鏈接到程序?qū)ο?/b>。
程序?qū)ο罂梢枣溄佣鄠€著色器對象。
在OpenGL ES中,每個程序?qū)ο蟊仨氝B接一個頂點(diǎn)著色器和一個片段著色器。程序?qū)ο蟊绘溄訛橛糜阡秩镜淖詈蟆翱蓤?zhí)行程序”。
獲得鏈接后的著色器對象的步驟:
創(chuàng)建一個頂色器對象和一個片段著色器對象
將著色器源代碼連接到每個著色器對象
編譯著色器對象
創(chuàng)建一個程序?qū)ο?/b>
將編譯后的著色器連接到程序?qū)ο?/i>
鏈接程序?qū)ο?/p>
下面結(jié)合著OpenGL ES的API
創(chuàng)建和編譯一個著色器
創(chuàng)建著色器
第一步是創(chuàng)建著色器: type: 創(chuàng)建的著色器類型可以是:GL_VERTEX_SHADER 或者GL_FRAGMENT_SHADER// 返回值:指向著色器的句柄GLuintglCreateShader(GLenum type);
刪除著色器
當(dāng)使用完著色器對象的時候,可以刪除著色器:
?shader: 要刪除的著色器對象的句柄voidglDeleteShader(GLuint shader);
注意:如果一個著色器連接到一個程序?qū)ο?,調(diào)用glDeleteShader不會立刻刪除著色器,而是將著色器標(biāo)記為刪除,在著色器不再連接任何程序?qū)ο髸r,內(nèi)存將被釋放。
給著色器對象提供源代碼
創(chuàng)建了著色器對象之后,就是給著色器對象提供源代碼,著色器源代碼以字符串的形式提供:
?shader: 指向著色器對象的句柄
?count: 著色器源代碼字符串的數(shù)量。著色器可以由多個源字符串組成,但是每個著色器只能有一個main函數(shù)
?string: 指向著色器源代碼的字符串指針
?length: 指向保存著多個(如果有多個)源代碼字符串大小的整型數(shù)組指針
voidglShaderSource(GLuint shader,? ? ? ? ? ? ? ? ? ? ? ? ? ? GLsizei count,constGLchar *conststring,constGLint *length );
編譯著色器
指定完著色器源代碼之后,下一步就是用glCompileShader編譯著色器:
void glCompileShader(GLuint shader);
可以用glGetShaderiv的GL_COMPILE_STATUS參數(shù)查詢編譯的信息
查詢著色器狀態(tài)信息
?shader: 著色器句柄
/* pname: 要查詢的信息的參數(shù):
? ? ? ? ? ? ? ? ? GL_COMPILE_STATUS: 編譯狀態(tài)
? ? ? ? ? ? ? ? ? GL_DELETE_STATUS: 著色器是否用glDeleteShader標(biāo)記為刪除
? ? ? ? ? ? ? ? ? GL_INFO_LOG_LENGTH: 編譯信息日志長度
? ? ? ? ? ? ? ? ? GL_SHADER_SOURCE_LENGTH: 著色器源代碼長度? ? ? ?
? ? ? ? ? ? ? ? ? GL_SHADER_TYPE: 著色器類型
*/// params: 指向 “查詢結(jié)果” 的整數(shù)存儲位置的指針voidglGetShaderiv(GLuint shader, GLenum pname, GLint *params);
檢查著色器是否編譯成功,用GL_COMPILE_STATUS參數(shù),成功編譯,params結(jié)果是GL_TRUE,編譯失敗GL_FALSE,編譯錯誤信息會寫入信息日志。即使編譯成功,也會在信息日志中寫入信息。
可以用GL_INFO_LOG_LENGTH查詢?nèi)罩镜拈L度。日志可以用glGetShaderInfoLog檢索。
獲取信息日志
// maxLength: 保存信息日志的緩沖區(qū)大小// length: 要寫入的信息日志的長度,減去null終止符// infoLog: 指向保存信息日志的字符緩沖區(qū)的指針voidglGetShaderInfoLog(GLuint shader,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GLsizei maxLength,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GLsizei *length,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GLchar *infoLog);
創(chuàng)建程序?qū)ο?/b>
程序?qū)ο笫且粋€容器對象,可以將著色器對象與之相連接,并鏈接到一個最終的可執(zhí)行程序。操作程序?qū)ο蟮腁PI與著色器的API比較相似。
// glCreateProgram沒有參數(shù),返回一個指向新程序?qū)ο蟮木浔鶪LuintglCreateProgram();
刪除程序?qū)ο?/b>
// program: 要刪除的程序?qū)ο蟮木浔鷙oidglDeleteProgram(GLuint program);
連接 程序?qū)ο?和 著色器對象
// program: 程序?qū)ο蟮木浔?/ shader: 著色器對象的句柄voidglAttachShader(GLuint program, GLuint shader);
注意:這個函數(shù)將著色器連接到指定的程序。著色器可以在任何時候連接,著色器連接到程序之前不一定需要編譯,甚至可以沒有源代碼。唯一的要求是:每一個程序?qū)ο蟊仨氂星抑挥幸粋€頂點(diǎn)著色器和一個片段著色器與之相連。
可以用glDetachShader斷開連接。
斷開 連接
voidglDetachShader(GLuint program, GLuint shader);
鏈接生成最終的可執(zhí)行程序
前提:程序連接了著色器,并且著色器編譯成功。
voidglLinkProgram(GLuint program);
鏈接操作負(fù)責(zé)生成最終的可執(zhí)行程序,生成在硬件上運(yùn)行的最終硬件指令。鏈接操作將檢查各種對象的數(shù)量,確保成功的鏈接。
鏈接程序?qū)⒋_保:
確保Vertex Shader寫入Fragment Shader的輸出變量,和Fragment Shader使用的輸入變量,有相同的聲明。
確保在Vertex Shader和Fragment Shader中聲明的統(tǒng)一變量和統(tǒng)一變量緩沖區(qū)的類型相同
確保最終的程序符合具體實(shí)現(xiàn)的限制,例如,屬性、統(tǒng)一變量或者輸入輸出著色器變量的數(shù)量
查詢鏈接狀態(tài)
上面說過 查詢shader的編譯狀態(tài)glGetShaderiv,下面是查詢程序的鏈接鏈接狀態(tài)glGetProgramiv
// pname: 要獲取的參數(shù)信息voidglGetProgramiv(GLuint program, GLenum pname, GLint *params);
要檢查鏈接是否成功,可以查詢GL_LINK_STATUS,和著色器一樣,程序?qū)ο蟠鎯υ谝粋€信息日志,日志的長度可以用GL_INFO_LOG_LENGTH來查詢
獲取程序的日志信息
// 參數(shù)跟著色器部分一樣voidglGetProgramInfoLog(GLuint program,
? ? ? ? ? ? ? ? ? ? ? ? ? GLsizei maxLength,
? ? ? ? ? ? ? ? ? ? ? ? ? GLsizei *length,
? ? ? ? ? ? ? ? ? ? ? ? ? GLchar *infoLog);
程序成功鏈接后,就已經(jīng)差不多為使用它渲染做好了準(zhǔn)備。但是在這之前,我們需要檢查程序是否有效,即:鏈接成功并不能保證執(zhí)行成功,例如,應(yīng)用程序沒有把有效的紋理綁定到采樣器,這種錯誤在鏈接的時候我們無法知道,但是在繪圖的時候會出現(xiàn),可以調(diào)用glValidateProgram來校驗(yàn)
校驗(yàn)應(yīng)用程序有效性
voidglValidateProgram(GLuint program);
校驗(yàn)的結(jié)果可以用glGetProgramiv來查詢,pname參數(shù)使用GL_VALIDATE_STATUS來檢查,同時信息日志也會更新。
注意:glValidateProgram是一個比較耗時的操作,一般只是用作調(diào)試。
在渲染之前,還有一件事要做:把應(yīng)用程序設(shè)置成活動程序
應(yīng)用程序設(shè)置成 活動程序
voidglUseProgram(GLuint program);
設(shè)置成活動程序之后,就可以開始渲染了。
學(xué)習(xí)相關(guān)的原理寫的demo代碼為了更好的了解著色器和程序的下載demo 代碼里面也有詳細(xì)的講解注釋 地址:
https://github.com/wangxiaokui/WangLearnOpenGL_ES
整篇文章參考的(鏈接:http://www.itdecent.cn/p/7c43d0c2566f)覺得寫的不錯的,直接保存了