OpenGL著色器(shader)語言
典型結(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í)完成的)。

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


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

支持多屬性:



高級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緩沖對象。

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


必須為每個(gè)著色器共用的uniform設(shè)置綁定點(diǎn)。
之后將uniform緩沖對象綁定到同樣的綁定點(diǎn)上,

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

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

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