GLSL

OpenGL著色器(shader)語言

典型結(jié)構(gòu):

典型結(jié)構(gòu)

基本數(shù)據(jù)類型:int, float, double, uint, bool?

GLSL容器類型:vector, matrix

向量類型

使用.操作符引用成員,如坐標(biāo)(x, y, z, w),顏色(r, g, b, a),紋理坐標(biāo)(s, t, p, q)

分量重組:

vec2 someVec;

vec4 differentVec = someVec.xyxx;

vec3 anotherVec = differentVec.zyw;

vec4 otherVec = someVec.xxxx + anotherVec.yxzy;

vec2 vect = vec2(0.5f,0.7f);

vec4 result = vec4(vect,0.0f,0.0f);

vec4 otherResult = vec4(result.xyz,1.0f);

頂點(diǎn)著色器:使用location這一元數(shù)據(jù)指定輸入變量,這樣我們才可以在CPU上配置頂點(diǎn)屬性。頂點(diǎn)著色器需要為它的輸入提供一個(gè)額外的layout標(biāo)識,這樣我們才能把它鏈接到頂點(diǎn)數(shù)據(jù)。

片段著色器:使用vec4顏色輸出變量,若未定義輸出顏色,則默認(rèn)為黑色或白色

各著色器數(shù)據(jù)交流:從一個(gè)著色器向另一個(gè)著色器發(fā)送數(shù)據(jù),必須在發(fā)送方著色器中聲明一個(gè)輸出,在接收方著色器中聲明一個(gè)類似的輸入。當(dāng)類型和名字都一樣的時(shí)候,OpenGL就會把兩個(gè)變量鏈接到一起,它們之間就能發(fā)送數(shù)據(jù)了(這是在鏈接程序?qū)ο髸r(shí)完成的)。

著色器實(shí)例

Uniform是一種從CPU中的應(yīng)用向GPU中的著色器發(fā)送數(shù)據(jù)的方式,但uniform和頂點(diǎn)屬性有些不同。首先,uniform是全局的(Global)。全局意味著uniform變量必須在每個(gè)著色器程序?qū)ο笾卸际仟?dú)一無二的,而且它可以被著色器程序的任意著色器在任意階段訪問。第二,無論你把uniform值設(shè)置成什么,uniform會一直保存它們的數(shù)據(jù),直到它們被重置或更新。

uniform變量定義
uniform變量在OpenGL代碼中使用

我們可以通過glUniform4f函數(shù)設(shè)置uniform值。注意,查詢uniform地址不要求你之前使用過著色器程序,但是更新一個(gè)unform之前你必須先使用程序(調(diào)用glUseProgram),因?yàn)樗窃诋?dāng)前激活的著色器程序中設(shè)置unform的。

uniform函數(shù)有許多,但命名方式遵循一定的規(guī)律:

glUniform函數(shù)添加后綴

支持多屬性:

頂點(diǎn)著色器
VBO存儲
VAO使能多屬性

高級GLSL

GLSL的內(nèi)建變量

gl_Position:頂點(diǎn)著色器裁剪空間輸出的位置向量

gl_PointSize:用于基本圖元GL_POINTS,設(shè)置點(diǎn)的大小,類型為float;使用前需開啟

glEnable(GL_PROGRAM_POINT_SIZE);

gl_VertexID:整型變量,存儲繪制的當(dāng)前頂點(diǎn)的id。進(jìn)行索引渲染是,它保存著當(dāng)前繪制頂點(diǎn)的索引,其他時(shí)候保存的是從渲染開始起直到當(dāng)前處理的這個(gè)頂點(diǎn)的編號。

片段著色器的變量

gl_FragCoord:它的z元素和特定的片段的深度相等;x,y是當(dāng)前片段的窗口坐標(biāo)

gl_FrontFacing:bool型,若當(dāng)前片段是正面的一部分值為true,反之為false??梢愿鶕?jù)其值為內(nèi)外賦予不同的紋理

gl_FragDepth:設(shè)置當(dāng)前片段的深度值,若不設(shè)置值則采用gl_FragCoord.z的值??梢允褂蒙疃葪l件重新聲明這個(gè)變量

layout (depth_<condition>) out float gl_FragDepth;

condition可能取值:例如depth_greater

any ? ? ? ? ? ? ? 默認(rèn)值. 前置深度測試是關(guān)閉的

greater ? ? ? ? 深度值只能比gl_FragCoord.z大

less ? ? ? ? ? ? ? 深度值只能設(shè)置得比gl_FragCoord.z小

unchanged ?如果寫入gl_FragDepth, 就會寫gl_FragCoord.z

接口塊

使用in, out關(guān)鍵字聲明,如果接口塊的名字一致,in塊和out塊的數(shù)據(jù)會聯(lián)系起來

out ?VS_OUT{

? ? ? vec2 TexCoords;

} vs_out;

in VS_OUT{

? ? ? ?vec2 TexCoords;

} fs_in;

塊的成員使用.運(yùn)算符來引用;

Uniform緩沖對象

uniform緩沖對象比單獨(dú)的uniform有很多好處。第一,一次設(shè)置多個(gè)uniform比一次設(shè)置一個(gè)速度快。第二,如果改變一個(gè)橫跨多個(gè)著色器的uniform,在uniform緩沖中只需更改一次。第三,使用uniform緩沖對象可以在著色器中使用更多的uniform。OpenGL有一個(gè)對可使用uniform數(shù)據(jù)的數(shù)量的限制,可以用GL_MAX_VERTEX_UNIFORM_COMPONENTS來獲取。當(dāng)使用uniform緩沖對象中,這個(gè)限制的閾限會更高。所以無論何時(shí),當(dāng)達(dá)到了uniform的最大使用數(shù)量(比如做骨骼動畫的時(shí)候),可以使用uniform緩沖對象。

uniform塊布局

GLSL 默認(rèn)使用的uniform內(nèi)存布局叫做共享布局(shared layout),叫共享是因?yàn)橐坏┢屏勘挥布x,它們就會持續(xù)地被多個(gè)程序所共享。使用共享布局,GLSL可以為了優(yōu)化而重新放置uniform變量,只要變量的順序保持完整。

使用uniform緩沖

創(chuàng)建uniform緩沖

之后往緩沖中更新或插入數(shù)據(jù),可綁定到uboExampleBlock上,并使用glBufferSubData來更新它的內(nèi)存。只需要更新這個(gè)uniform緩沖一次,所有的使用這個(gè)緩沖著色器就都會使用它更新的數(shù)據(jù)了。

在OpenGL環(huán)境(context)中,定義了若干綁定點(diǎn)(binding points),可以把一個(gè)uniform緩沖鏈接上去。當(dāng)創(chuàng)建了一個(gè)uniform緩沖,把它鏈接到一個(gè)綁定點(diǎn)上,同時(shí)也把著色器中uniform塊鏈接到同一個(gè)綁定點(diǎn)上,這樣就把它們鏈接到一起了。下面的圖標(biāo)表示了這點(diǎn):

綁定點(diǎn)
綁定著色器的uniform到綁定點(diǎn)

必須為每個(gè)著色器共用的uniform設(shè)置綁定點(diǎn)。

之后將uniform緩沖對象綁定到同樣的綁定點(diǎn)上,

綁定uniform緩沖到綁定點(diǎn)上

從OpenGL4.2起,可以在著色器中通過添加另一個(gè)布局標(biāo)識符來儲存一個(gè)uniform塊的綁定點(diǎn),顯式設(shè)置綁定點(diǎn):

binding屬性

最后向uniform緩沖中添加數(shù)據(jù),

添加數(shù)據(jù)到uniform緩沖中



圖片和一些文字來源于https://learnopengl-cn.github.io,本人收集作為筆記,如有侵權(quán),望告知


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

相關(guān)閱讀更多精彩內(nèi)容

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