著色器渲染原理;著色器和程序的關(guān)系

著色器進(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 ShaderFragment 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)覺得寫的不錯的,直接保存了

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

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