日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

glsl基础

發(fā)布時間:2024/8/23 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 glsl基础 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.



目錄[-]

  • 變量
  • 基本類型
  • 結(jié)構(gòu)體
  • 數(shù)組
  • 修飾符
  • 內(nèi)置變量
  • 表達式
  • 操作符
  • 數(shù)組訪問
  • 構(gòu)造函數(shù)
  • 成分選擇
  • 控制流
  • 循環(huán)
  • if/else
  • discard
  • 函數(shù)

變量

GLSL的變量命名方式與C語言類似。變量的名稱可以使用字母,數(shù)字以及下劃線,但變量名不能以數(shù)字開頭,還有變量名不能以gl_作為前綴,這個是GLSL保留的前綴,用于GLSL的內(nèi)部變量。當然還有一些GLSL保留的名稱是不能夠作為變量的名稱的。

基本類型

除了布爾型,整型,浮點型基本類型外,GLSL還引入了一些在著色器中經(jīng)常用到的類型作為基本類型。這些基本類型都可以作為結(jié)構(gòu)體內(nèi)部的類型。如下表:

類型描述
void跟C語言的void類似,表示空類型。作為函數(shù)的返回類型,表示這個函數(shù)不返回值。
bool布爾類型,可以是true 和false,以及可以產(chǎn)生布爾型的表達式。
int整型 代表至少包含16位的有符號的整數(shù)??梢允鞘M制的,十六進制的,八進制的。
float浮點型
bvec2包含2個布爾成分的向量
bvec3包含3個布爾成分的向量
bvec4包含4個布爾成分的向量
ivec2包含2個整型成分的向量
ivec3包含3個整型成分的向量
ivec4包含4個整型成分的向量
mat2 或者 mat2x22x2的浮點數(shù)矩陣類型
mat3或者mat3x33x3的浮點數(shù)矩陣類型
mat4x44x4的浮點矩陣
mat2x32列3行的浮點矩陣(OpenGL的矩陣是列主順序的)
mat2x42列4行的浮點矩陣
mat3x23列2行的浮點矩陣
mat3x43列4行的浮點矩陣
mat4x24列2行的浮點矩陣
mat4x34列3行的浮點矩陣
sampler1D用于內(nèi)建的紋理函數(shù)中引用指定的1D紋理的句柄。只可以作為一致變量或者函數(shù)參數(shù)使用
sampler2D二維紋理句柄
sampler3D三維紋理句柄
samplerCubecube map紋理句柄
sampler1DShadow一維深度紋理句柄
sampler2DShadow二維深度紋理句柄

結(jié)構(gòu)體

結(jié)構(gòu)體

結(jié)構(gòu)體可以組合基本類型和數(shù)組來形成用戶自定義的類型。在定義一個結(jié)構(gòu)體的同時,你可以定義一個結(jié)構(gòu)體實例?;蛘吆竺嬖俣x。

struct?surface?{float?indexOfRefraction;vec3?color;float?turbulence;}?mySurface;surface?secondeSurface;

你可以通過=為結(jié)構(gòu)體賦值,或者使用 ==,!=來判斷兩個結(jié)構(gòu)體是否相等。

mySurface = secondSurface;

mySurface == secondSurface;

只有結(jié)構(gòu)體中的每個成分都相等,那么這兩個結(jié)構(gòu)體才是相等的。訪問結(jié)構(gòu)體的內(nèi)部成員使用. 來訪問。

vec3 color = mySurface.color + secondSurface.color;

結(jié)構(gòu)體至少包含一個成員。固定大小的數(shù)組也可以被包含在結(jié)構(gòu)體中。GLSL的結(jié)構(gòu)體不支持嵌套定義。只有預先聲明的結(jié)構(gòu)體可以嵌套其中。

struct?myStruct?{vec3?points[3];?//固定大小的數(shù)組是合法的surface?surf;??//可以,之前已經(jīng)定義了struct?velocity?{??//不合法float?speed;vec3?direction;}?velo;subSurface?sub;?//不合法,沒有預先聲明;};struct?subSurface?{??int?id; };

數(shù)組

GLSL中只可以使用一維的數(shù)組。數(shù)組的類型可以是一切基本類型或者結(jié)構(gòu)體。下面的幾種數(shù)組聲明是合法的:

surface?mySurfaces[]; vec4?lightPositions[8]; vec4?lightPos[]?=?lightPositions;const?int?numSurfaces?=?5; surface?myFiveSurfaces[numSurfaces];float[5]?values;

指定顯示大小的數(shù)組可以作為函數(shù)的參數(shù)或者使返回值,也可以作為結(jié)構(gòu)體的成員.數(shù)組類型內(nèi)建了一個length()函數(shù),可以返回數(shù)組的長度。

lightPositions.length() //返回數(shù)組的大小 8

最后,你不能定義數(shù)組的數(shù)組。

修飾符

變量的聲明可以使用如下的修飾符。

修飾符描述
const常量值必須在聲明是初始化。它是只讀的不可修改的。
attribute表示只讀的頂點數(shù)據(jù),只用在頂點著色器中。數(shù)據(jù)來自當前的頂點狀態(tài)或者頂點數(shù)組。它必須是全局范圍聲明的,不能再函數(shù)內(nèi)部。一個attribute可以是浮點數(shù)類型的標量,向量,或者矩陣。不可以是數(shù)組或則結(jié)構(gòu)體
uniform一致變量。在著色器執(zhí)行期間一致變量的值是不變的。與const常量不同的是,這個值在編譯時期是未知的是由著色器外部初始化的。一致變量在頂點著色器和片段著色器之間是共享的。它也只能在全局范圍進行聲明。
varying頂點著色器的輸出。例如顏色或者紋理坐標,(插值后的數(shù)據(jù))作為片段著色器的只讀輸入數(shù)據(jù)。必須是全局范圍聲明的全局變量??梢允歉↑c數(shù)類型的標量,向量,矩陣。不能是數(shù)組或者結(jié)構(gòu)體。
centorid varying在沒有多重采樣的情況下,與varying是一樣的意思。在多重采樣時,centorid varying在光柵化的圖形內(nèi)部進行求值而不是在片段中心的固定位置求值。
invariant(不變量)用于表示頂點著色器的輸出和任何匹配片段著色器的輸入,在不同的著色器中計算產(chǎn)生的值必須是一致的。所有的數(shù)據(jù)流和控制流,寫入一個invariant變量的是一致的。編譯器為了保證結(jié)果是完全一致的,需要放棄那些可能會導致不一致值的潛在的優(yōu)化。除非必要,不要使用這個修飾符。在多通道渲染中避免z-fighting可能會使用到。
in用在函數(shù)的參數(shù)中,表示這個參數(shù)是輸入的,在函數(shù)中改變這個值,并不會影響對調(diào)用的函數(shù)產(chǎn)生副作用。(相當于C語言的傳值),這個是函數(shù)參數(shù)默認的修飾符
out用在函數(shù)的參數(shù)中,表示該參數(shù)是輸出參數(shù),值是會改變的。
inout用在函數(shù)的參數(shù),表示這個參數(shù)即是輸入?yún)?shù)也是輸出參數(shù)。

內(nèi)置變量

內(nèi)置變量可以與固定函數(shù)功能進行交互。在使用前不需要聲明。頂點著色器可用的內(nèi)置變量如下表:

名稱類型描述
gl_Colorvec4輸入屬性-表示頂點的主顏色
gl_SecondaryColorvec4輸入屬性-表示頂點的輔助顏色
gl_Normalvec3輸入屬性-表示頂點的法線值
gl_Vertexvec4輸入屬性-表示物體空間的頂點位置
gl_MultiTexCoordnvec4輸入屬性-表示頂點的第n個紋理的坐標
gl_FogCoordfloat輸入屬性-表示頂點的霧坐標
gl_Positionvec4輸出屬性-變換后的頂點的位置,用于后面的固定的裁剪等操作。所有的頂點著色器都必須寫這個值。
gl_ClipVertexvec4輸出坐標,用于用戶裁剪平面的裁剪
gl_PointSizefloat點的大小
gl_FrontColorvec4正面的主顏色的varying輸出
gl_BackColorvec4背面主顏色的varying輸出
gl_FrontSecondaryColorvec4正面的輔助顏色的varying輸出
gl_BackSecondaryColorvec4背面的輔助顏色的varying輸出
gl_TexCoord[]vec4紋理坐標的數(shù)組varying輸出
gl_FogFragCoordfloat霧坐標的varying輸出

片段著色器的內(nèi)置變量如下表:

名稱類型描述
gl_Colorvec4包含主顏色的插值只讀輸入
gl_SecondaryColorvec4包含輔助顏色的插值只讀輸入
gl_TexCoord[]vec4包含紋理坐標數(shù)組的插值只讀輸入
gl_FogFragCoordfloat包含霧坐標的插值只讀輸入
gl_FragCoordvec4只讀輸入,窗口的x,y,z和1/w
gl_FrontFacingbool只讀輸入,如果是窗口正面圖元的一部分,則這個值為true
gl_PointCoordvec2點精靈的二維空間坐標范圍在(0.0, 0.0)到(1.0, 1.0)之間,僅用于點圖元和點精靈開啟的情況下。
gl_FragData[]vec4使用glDrawBuffers輸出的數(shù)據(jù)數(shù)組。不能與gl_FragColor結(jié)合使用。
gl_FragColorvec4輸出的顏色用于隨后的像素操作
gl_FragDepthfloat輸出的深度用于隨后的像素操作,如果這個值沒有被寫,則使用固定功能管線的深度值代替

表達式

操作符

GLSL語言的操作符與C語言相似。如下表(操作符的優(yōu)先級從高到低排列)

操作符描述
()用于表達式組合,函數(shù)調(diào)用,構(gòu)造
[]數(shù)組下標,向量或矩陣的選擇器
.結(jié)構(gòu)體和向量的成員選擇
++ --前綴或后綴的自增自減操作符
+ – !一元操作符,表示正 負 邏輯非
* /乘 除操作符
+ -二元操作符 表示加 減操作
<> <= >= == !=小于,大于,小于等于, 大于等于,等于,不等于 判斷符
&& || ^^邏輯與 ,或,? 異或
?:條件判斷符
= += –= *=? /=賦值操作符
,表示序列

像 求地址的& 和 解引用的 * 操作符不再GLSL中出現(xiàn),因為GLSL不能直接操作地址。類型轉(zhuǎn)換操作也是不允許的。 位操作符(&,|,^,~, <<, >> ,&=, |=, ^=, <<=, >>=)是GLSL保留的操作符,將來可能會被使用。還有求模操作(%,%=)也是保留的。

數(shù)組訪問

數(shù)組的下標從0開始。合理的范圍是[0, size - 1]。跟C語言一樣。如果數(shù)組訪問越界了,那行為是未定義的。如果著色器的編譯器在編譯時知道數(shù)組訪問越界了,就會提示編譯失敗。

vec4 myColor, ambient, diffuse[6], specular[6];

myColor = ambient + diffuse[4] + specular[4];

構(gòu)造函數(shù)

構(gòu)造函數(shù)可以用于初始化包含多個成員的變量,包括數(shù)組和結(jié)構(gòu)體。構(gòu)造函數(shù)也可以用在表達式中。調(diào)用方式如下:

vec3 myNormal = vec3(1.0, 1.0, 1.0);

greenTint = myColor + vec3(0.0, 1.0, 0.0);

ivec4 myColor = ivec4(255);

還可以使用混合標量和向量的方式來構(gòu)造,只要你的元素足以填滿該向量。

vec4 color = vec4(1.0, vec2(0.0, 1.0), 1.0);

vec3 v = vec3(1.0, 10.0, 1.0);

vec3 v1 = vec3(v);

vec2 fv = vec2(5.0, 6.0);

float f = float(fv);?//用x值2.5構(gòu)造,y值被舍棄

對于矩陣,OpenGL中矩陣是列主順序的。如果只傳了一個值,則會構(gòu)造成對角矩陣,其余的元素為0.

mat3 m3 = mat3(1.0);

構(gòu)造出來的矩陣式:

1.0 0.0 0.0

0.0 1.0 0.0

0.0 0.0 1.0

mat2 matrix1 = mat2(1.0, 0.0, 0.0, 1.0);

mat2 matrix2 = mat2(vec2(1.0, 0.0), vec2(0.0, 1.0));

mat2 matrix3 = mat2(1.0);?

mat2 matrix4 = mat2(mat4(2.0));?//會取?4x4矩陣左上角的2x2矩陣。

構(gòu)造函數(shù)可以用于標量數(shù)據(jù)類型的轉(zhuǎn)換。GLSL不支持隱式或顯示的轉(zhuǎn)換,只能通過構(gòu)造函數(shù)來轉(zhuǎn)。其中int轉(zhuǎn)為float值是一樣的。float轉(zhuǎn)為int則小數(shù)部分被丟棄。int或float轉(zhuǎn)為bool,0和0.0轉(zhuǎn)為false,其余的值轉(zhuǎn)為true. bool轉(zhuǎn)為int或float,false值轉(zhuǎn)為0和0.0,true轉(zhuǎn)為1和1.0.

float f = 1.7;

int I = int(f); // I = 1

數(shù)組的初始化,可以在構(gòu)造函數(shù)中傳入值來初始化數(shù)組中對應的每一個值。

ivec2 position[3] = ivec2[3]((0,0), (1,1), (2,2));

ivec2 pos2[3] = ivec2[]((3,3), (2,1), (3,1));

構(gòu)造函數(shù)也可以對結(jié)構(gòu)體進行初始化。其中順序和類型要一一對應。

struct?surface?{??int??index;vec3?color;??float?rotate; };surface?mySurface?=?surface(3,?vec3(red,?green,?blue),?0.5);

成分選擇

向量中單獨的成分可以通過{x,y,z,w},{r,g,b,a}或者{s,t,p,q}的記法來表示。這些不同的記法用于頂點,顏色,紋理坐標。在成分選擇中,你不可以混合使用這些記法。其中{s,t,p,q}中的p替換了紋理的r坐標,因為與顏色r重復了。下面是用法舉例:

vec3?myVec?=?{0.5,?0.35,?0.7};float?r?=?myVec.r;float?myYz?=?myVec.yz;float?myQ?=?myVec.q;//出錯,數(shù)組越界訪問,q代表第四個元素float?myRY?=?myVec.ry;?//不合法,混合使用記法

較特殊的使用方式,你可以重復向量中的元素,或者顛倒其順序。如:

vec3?yxz?=?myVec.yxz;?//調(diào)換順序vec4?mySSTT?=?myVec.sstt;?//重復其中的值

在賦值是,也可以選擇你想要的順序,但是不能重復其中的成分。

vec4?myColor?=?{0.0,?1.0,?2.0,?1.0}; myColor.x?=?-1.0; myColor.yz?=?vec2(3.0,?5.0); myColor.wx?=?vec2(1.0,?3.0); myColor.zz?=?vec2(2.0,?3.0);?//不合法

我們也可以通過使用下標來訪問向量或矩陣中的元素。如果越界那行為將是未定義的。

float myY = myVec[1];

在矩陣中,可以通過一維的下標來獲得該列的向量(OpenGL的矩陣是列主順序的)。二維的小標來獲得向量中的元素。

mat3?myMat?=?mat3(1.0); vec3?myVec?=?myMat[0];?//獲得第一列向量?1.0,?0.0,?0.0float?f?=?myMat[0][0];?//?第一列的第一個向量。

控制流

循環(huán)

與C和C++相似,GLSL語言也提供了for, while, do/while的循環(huán)方式。使用continue跳入下一次循環(huán),break結(jié)束循環(huán)。

for?(l?=?0;?l?<?numLights;?l++) {if?(!lightExists[l])continue;color?+=?light[l]; }while?(i?<?num) {sum?+=?color[i];i++; }do{color?+=?light[lightNum];lightNum--; }while?(lightNum?>?0)

if/else

color?=?unlitColor;if?(numLights?>?0) {color?=?litColor; }else{color?=?unlitColor; }

discard

片段著色器中有一種特殊的控制流成為discard。使用discard會退出片段著色器,不執(zhí)行后面的片段著色操作。片段也不會寫入幀緩沖區(qū)。

if (color.a < 0.9)

discard;

函數(shù)

在每個shader中必須有一個main函數(shù)。main函數(shù)中的void參數(shù)是可選的,但返回值是void時必須的。

void?main(void) {... }

GLSL中的函數(shù),必須是在全局范圍定義和聲明的。不能在函數(shù)定義中聲明或定義函數(shù)。函數(shù)必須有返回類型,參數(shù)是可選的。參數(shù)的修飾符(in, out, inout, const等)是可選的。

//函數(shù)聲明bool?isAnyNegative(const?vec4?v);//函數(shù)調(diào)用void?main(void) {bool?isNegative?=?isAnyNegative(gl_Color);... }//定義bool?isAnyNegative(const?vec4?v) {if?(v.x?<?0.0?||?v.y?<?0.0?||?v.z?<?0.0?||?v.w?<?0.0)return?true;elsereturn?false; }

結(jié)構(gòu)體和數(shù)組也可以作為函數(shù)的參數(shù)。如果是數(shù)組作為函數(shù)的參數(shù),則必須制定其大小。在調(diào)用傳參時,只傳數(shù)組名就可以了。

vec4?sumVectors(int?sumSize,?vec4?v[10]);void?main() {vec4?myColors[10];...vec4?sumColor?=?sumVectors(5,?myColors); }vec4?sumVectors(int?sumSize,?vec4?v[10]) {int?i?=?0;vec4?sum?=?vec4(0.0);for(;?i?<?sumSize;?++i){sum?+=?v[i];?}return?sum; }

GLSL的函數(shù)是支持重載的。函數(shù)可以同名但其參數(shù)類型或者參數(shù)個數(shù)不同即可。

float?sum(float?a,?float?b) {return?a?+?b; }vec3?sum(vec3?v1,?vec3?v2) {return?v1?+?v2; }

目錄[-]

  • 變量
  • 基本類型
  • 結(jié)構(gòu)體
  • 數(shù)組
  • 修飾符
  • 內(nèi)置變量
  • 表達式
  • 操作符
  • 數(shù)組訪問
  • 構(gòu)造函數(shù)
  • 成分選擇
  • 控制流
  • 循環(huán)
  • if/else
  • discard
  • 函數(shù)

變量

GLSL的變量命名方式與C語言類似。變量的名稱可以使用字母,數(shù)字以及下劃線,但變量名不能以數(shù)字開頭,還有變量名不能以gl_作為前綴,這個是GLSL保留的前綴,用于GLSL的內(nèi)部變量。當然還有一些GLSL保留的名稱是不能夠作為變量的名稱的。

基本類型

除了布爾型,整型,浮點型基本類型外,GLSL還引入了一些在著色器中經(jīng)常用到的類型作為基本類型。這些基本類型都可以作為結(jié)構(gòu)體內(nèi)部的類型。如下表:

類型描述
void跟C語言的void類似,表示空類型。作為函數(shù)的返回類型,表示這個函數(shù)不返回值。
bool布爾類型,可以是true 和false,以及可以產(chǎn)生布爾型的表達式。
int整型 代表至少包含16位的有符號的整數(shù)。可以是十進制的,十六進制的,八進制的。
float浮點型
bvec2包含2個布爾成分的向量
bvec3包含3個布爾成分的向量
bvec4包含4個布爾成分的向量
ivec2包含2個整型成分的向量
ivec3包含3個整型成分的向量
ivec4包含4個整型成分的向量
mat2 或者 mat2x22x2的浮點數(shù)矩陣類型
mat3或者mat3x33x3的浮點數(shù)矩陣類型
mat4x44x4的浮點矩陣
mat2x32列3行的浮點矩陣(OpenGL的矩陣是列主順序的)
mat2x42列4行的浮點矩陣
mat3x23列2行的浮點矩陣
mat3x43列4行的浮點矩陣
mat4x24列2行的浮點矩陣
mat4x34列3行的浮點矩陣
sampler1D用于內(nèi)建的紋理函數(shù)中引用指定的1D紋理的句柄。只可以作為一致變量或者函數(shù)參數(shù)使用
sampler2D二維紋理句柄
sampler3D三維紋理句柄
samplerCubecube map紋理句柄
sampler1DShadow一維深度紋理句柄
sampler2DShadow二維深度紋理句柄

結(jié)構(gòu)體

結(jié)構(gòu)體

結(jié)構(gòu)體可以組合基本類型和數(shù)組來形成用戶自定義的類型。在定義一個結(jié)構(gòu)體的同時,你可以定義一個結(jié)構(gòu)體實例。或者后面再定義。

struct?surface?{float?indexOfRefraction;vec3?color;float?turbulence;}?mySurface;surface?secondeSurface;

你可以通過=為結(jié)構(gòu)體賦值,或者使用 ==,!=來判斷兩個結(jié)構(gòu)體是否相等。

mySurface = secondSurface;

mySurface == secondSurface;

只有結(jié)構(gòu)體中的每個成分都相等,那么這兩個結(jié)構(gòu)體才是相等的。訪問結(jié)構(gòu)體的內(nèi)部成員使用. 來訪問。

vec3 color = mySurface.color + secondSurface.color;

結(jié)構(gòu)體至少包含一個成員。固定大小的數(shù)組也可以被包含在結(jié)構(gòu)體中。GLSL的結(jié)構(gòu)體不支持嵌套定義。只有預先聲明的結(jié)構(gòu)體可以嵌套其中。

struct?myStruct?{vec3?points[3];?//固定大小的數(shù)組是合法的surface?surf;??//可以,之前已經(jīng)定義了struct?velocity?{??//不合法float?speed;vec3?direction;}?velo;subSurface?sub;?//不合法,沒有預先聲明;};struct?subSurface?{??int?id; };

數(shù)組

GLSL中只可以使用一維的數(shù)組。數(shù)組的類型可以是一切基本類型或者結(jié)構(gòu)體。下面的幾種數(shù)組聲明是合法的:

surface?mySurfaces[]; vec4?lightPositions[8]; vec4?lightPos[]?=?lightPositions;const?int?numSurfaces?=?5; surface?myFiveSurfaces[numSurfaces];float[5]?values;

指定顯示大小的數(shù)組可以作為函數(shù)的參數(shù)或者使返回值,也可以作為結(jié)構(gòu)體的成員.數(shù)組類型內(nèi)建了一個length()函數(shù),可以返回數(shù)組的長度。

lightPositions.length() //返回數(shù)組的大小 8

最后,你不能定義數(shù)組的數(shù)組。

修飾符

變量的聲明可以使用如下的修飾符。

修飾符描述
const常量值必須在聲明是初始化。它是只讀的不可修改的。
attribute表示只讀的頂點數(shù)據(jù),只用在頂點著色器中。數(shù)據(jù)來自當前的頂點狀態(tài)或者頂點數(shù)組。它必須是全局范圍聲明的,不能再函數(shù)內(nèi)部。一個attribute可以是浮點數(shù)類型的標量,向量,或者矩陣。不可以是數(shù)組或則結(jié)構(gòu)體
uniform一致變量。在著色器執(zhí)行期間一致變量的值是不變的。與const常量不同的是,這個值在編譯時期是未知的是由著色器外部初始化的。一致變量在頂點著色器和片段著色器之間是共享的。它也只能在全局范圍進行聲明。
varying頂點著色器的輸出。例如顏色或者紋理坐標,(插值后的數(shù)據(jù))作為片段著色器的只讀輸入數(shù)據(jù)。必須是全局范圍聲明的全局變量。可以是浮點數(shù)類型的標量,向量,矩陣。不能是數(shù)組或者結(jié)構(gòu)體。
centorid varying在沒有多重采樣的情況下,與varying是一樣的意思。在多重采樣時,centorid varying在光柵化的圖形內(nèi)部進行求值而不是在片段中心的固定位置求值。
invariant(不變量)用于表示頂點著色器的輸出和任何匹配片段著色器的輸入,在不同的著色器中計算產(chǎn)生的值必須是一致的。所有的數(shù)據(jù)流和控制流,寫入一個invariant變量的是一致的。編譯器為了保證結(jié)果是完全一致的,需要放棄那些可能會導致不一致值的潛在的優(yōu)化。除非必要,不要使用這個修飾符。在多通道渲染中避免z-fighting可能會使用到。
in用在函數(shù)的參數(shù)中,表示這個參數(shù)是輸入的,在函數(shù)中改變這個值,并不會影響對調(diào)用的函數(shù)產(chǎn)生副作用。(相當于C語言的傳值),這個是函數(shù)參數(shù)默認的修飾符
out用在函數(shù)的參數(shù)中,表示該參數(shù)是輸出參數(shù),值是會改變的。
inout用在函數(shù)的參數(shù),表示這個參數(shù)即是輸入?yún)?shù)也是輸出參數(shù)。

內(nèi)置變量

內(nèi)置變量可以與固定函數(shù)功能進行交互。在使用前不需要聲明。頂點著色器可用的內(nèi)置變量如下表:

名稱類型描述
gl_Colorvec4輸入屬性-表示頂點的主顏色
gl_SecondaryColorvec4輸入屬性-表示頂點的輔助顏色
gl_Normalvec3輸入屬性-表示頂點的法線值
gl_Vertexvec4輸入屬性-表示物體空間的頂點位置
gl_MultiTexCoordnvec4輸入屬性-表示頂點的第n個紋理的坐標
gl_FogCoordfloat輸入屬性-表示頂點的霧坐標
gl_Positionvec4輸出屬性-變換后的頂點的位置,用于后面的固定的裁剪等操作。所有的頂點著色器都必須寫這個值。
gl_ClipVertexvec4輸出坐標,用于用戶裁剪平面的裁剪
gl_PointSizefloat點的大小
gl_FrontColorvec4正面的主顏色的varying輸出
gl_BackColorvec4背面主顏色的varying輸出
gl_FrontSecondaryColorvec4正面的輔助顏色的varying輸出
gl_BackSecondaryColorvec4背面的輔助顏色的varying輸出
gl_TexCoord[]vec4紋理坐標的數(shù)組varying輸出
gl_FogFragCoordfloat霧坐標的varying輸出

片段著色器的內(nèi)置變量如下表:

名稱類型描述
gl_Colorvec4包含主顏色的插值只讀輸入
gl_SecondaryColorvec4包含輔助顏色的插值只讀輸入
gl_TexCoord[]vec4包含紋理坐標數(shù)組的插值只讀輸入
gl_FogFragCoordfloat包含霧坐標的插值只讀輸入
gl_FragCoordvec4只讀輸入,窗口的x,y,z和1/w
gl_FrontFacingbool只讀輸入,如果是窗口正面圖元的一部分,則這個值為true
gl_PointCoordvec2點精靈的二維空間坐標范圍在(0.0, 0.0)到(1.0, 1.0)之間,僅用于點圖元和點精靈開啟的情況下。
gl_FragData[]vec4使用glDrawBuffers輸出的數(shù)據(jù)數(shù)組。不能與gl_FragColor結(jié)合使用。
gl_FragColorvec4輸出的顏色用于隨后的像素操作
gl_FragDepthfloat輸出的深度用于隨后的像素操作,如果這個值沒有被寫,則使用固定功能管線的深度值代替

表達式

操作符

GLSL語言的操作符與C語言相似。如下表(操作符的優(yōu)先級從高到低排列)

操作符描述
()用于表達式組合,函數(shù)調(diào)用,構(gòu)造
[]數(shù)組下標,向量或矩陣的選擇器
.結(jié)構(gòu)體和向量的成員選擇
++ --前綴或后綴的自增自減操作符
+ – !一元操作符,表示正 負 邏輯非
* /乘 除操作符
+ -二元操作符 表示加 減操作
<> <= >= == !=小于,大于,小于等于, 大于等于,等于,不等于 判斷符
&& || ^^邏輯與 ,或,? 異或
?:條件判斷符
= += –= *=? /=賦值操作符
,表示序列

像 求地址的& 和 解引用的 * 操作符不再GLSL中出現(xiàn),因為GLSL不能直接操作地址。類型轉(zhuǎn)換操作也是不允許的。 位操作符(&,|,^,~, <<, >> ,&=, |=, ^=, <<=, >>=)是GLSL保留的操作符,將來可能會被使用。還有求模操作(%,%=)也是保留的。

數(shù)組訪問

數(shù)組的下標從0開始。合理的范圍是[0, size - 1]。跟C語言一樣。如果數(shù)組訪問越界了,那行為是未定義的。如果著色器的編譯器在編譯時知道數(shù)組訪問越界了,就會提示編譯失敗。

vec4 myColor, ambient, diffuse[6], specular[6];

myColor = ambient + diffuse[4] + specular[4];

構(gòu)造函數(shù)

構(gòu)造函數(shù)可以用于初始化包含多個成員的變量,包括數(shù)組和結(jié)構(gòu)體。構(gòu)造函數(shù)也可以用在表達式中。調(diào)用方式如下:

vec3 myNormal = vec3(1.0, 1.0, 1.0);

greenTint = myColor + vec3(0.0, 1.0, 0.0);

ivec4 myColor = ivec4(255);

還可以使用混合標量和向量的方式來構(gòu)造,只要你的元素足以填滿該向量。

vec4 color = vec4(1.0, vec2(0.0, 1.0), 1.0);

vec3 v = vec3(1.0, 10.0, 1.0);

vec3 v1 = vec3(v);

vec2 fv = vec2(5.0, 6.0);

float f = float(fv);?//用x值2.5構(gòu)造,y值被舍棄

對于矩陣,OpenGL中矩陣是列主順序的。如果只傳了一個值,則會構(gòu)造成對角矩陣,其余的元素為0.

mat3 m3 = mat3(1.0);

構(gòu)造出來的矩陣式:

1.0 0.0 0.0

0.0 1.0 0.0

0.0 0.0 1.0

mat2 matrix1 = mat2(1.0, 0.0, 0.0, 1.0);

mat2 matrix2 = mat2(vec2(1.0, 0.0), vec2(0.0, 1.0));

mat2 matrix3 = mat2(1.0);?

mat2 matrix4 = mat2(mat4(2.0));?//會取?4x4矩陣左上角的2x2矩陣。

構(gòu)造函數(shù)可以用于標量數(shù)據(jù)類型的轉(zhuǎn)換。GLSL不支持隱式或顯示的轉(zhuǎn)換,只能通過構(gòu)造函數(shù)來轉(zhuǎn)。其中int轉(zhuǎn)為float值是一樣的。float轉(zhuǎn)為int則小數(shù)部分被丟棄。int或float轉(zhuǎn)為bool,0和0.0轉(zhuǎn)為false,其余的值轉(zhuǎn)為true. bool轉(zhuǎn)為int或float,false值轉(zhuǎn)為0和0.0,true轉(zhuǎn)為1和1.0.

float f = 1.7;

int I = int(f); // I = 1

數(shù)組的初始化,可以在構(gòu)造函數(shù)中傳入值來初始化數(shù)組中對應的每一個值。

ivec2 position[3] = ivec2[3]((0,0), (1,1), (2,2));

ivec2 pos2[3] = ivec2[]((3,3), (2,1), (3,1));

構(gòu)造函數(shù)也可以對結(jié)構(gòu)體進行初始化。其中順序和類型要一一對應。

struct?surface?{??int??index;vec3?color;??float?rotate; };surface?mySurface?=?surface(3,?vec3(red,?green,?blue),?0.5);

成分選擇

向量中單獨的成分可以通過{x,y,z,w},{r,g,b,a}或者{s,t,p,q}的記法來表示。這些不同的記法用于頂點,顏色,紋理坐標。在成分選擇中,你不可以混合使用這些記法。其中{s,t,p,q}中的p替換了紋理的r坐標,因為與顏色r重復了。下面是用法舉例:

vec3?myVec?=?{0.5,?0.35,?0.7};float?r?=?myVec.r;float?myYz?=?myVec.yz;float?myQ?=?myVec.q;//出錯,數(shù)組越界訪問,q代表第四個元素float?myRY?=?myVec.ry;?//不合法,混合使用記法

較特殊的使用方式,你可以重復向量中的元素,或者顛倒其順序。如:

vec3?yxz?=?myVec.yxz;?//調(diào)換順序vec4?mySSTT?=?myVec.sstt;?//重復其中的值

在賦值是,也可以選擇你想要的順序,但是不能重復其中的成分。

vec4?myColor?=?{0.0,?1.0,?2.0,?1.0}; myColor.x?=?-1.0; myColor.yz?=?vec2(3.0,?5.0); myColor.wx?=?vec2(1.0,?3.0); myColor.zz?=?vec2(2.0,?3.0);?//不合法

我們也可以通過使用下標來訪問向量或矩陣中的元素。如果越界那行為將是未定義的。

float myY = myVec[1];

在矩陣中,可以通過一維的下標來獲得該列的向量(OpenGL的矩陣是列主順序的)。二維的小標來獲得向量中的元素。

mat3?myMat?=?mat3(1.0); vec3?myVec?=?myMat[0];?//獲得第一列向量?1.0,?0.0,?0.0float?f?=?myMat[0][0];?//?第一列的第一個向量。

控制流

循環(huán)

與C和C++相似,GLSL語言也提供了for, while, do/while的循環(huán)方式。使用continue跳入下一次循環(huán),break結(jié)束循環(huán)。

for?(l?=?0;?l?<?numLights;?l++) {if?(!lightExists[l])continue;color?+=?light[l]; }while?(i?<?num) {sum?+=?color[i];i++; }do{color?+=?light[lightNum];lightNum--; }while?(lightNum?>?0)

if/else

color?=?unlitColor;if?(numLights?>?0) {color?=?litColor; }else{color?=?unlitColor; }

discard

片段著色器中有一種特殊的控制流成為discard。使用discard會退出片段著色器,不執(zhí)行后面的片段著色操作。片段也不會寫入幀緩沖區(qū)。

if (color.a < 0.9)

discard;

函數(shù)

在每個shader中必須有一個main函數(shù)。main函數(shù)中的void參數(shù)是可選的,但返回值是void時必須的。

void?main(void) {... }

GLSL中的函數(shù),必須是在全局范圍定義和聲明的。不能在函數(shù)定義中聲明或定義函數(shù)。函數(shù)必須有返回類型,參數(shù)是可選的。參數(shù)的修飾符(in, out, inout, const等)是可選的。

//函數(shù)聲明bool?isAnyNegative(const?vec4?v);//函數(shù)調(diào)用void?main(void) {bool?isNegative?=?isAnyNegative(gl_Color);... }//定義bool?isAnyNegative(const?vec4?v) {if?(v.x?<?0.0?||?v.y?<?0.0?||?v.z?<?0.0?||?v.w?<?0.0)return?true;elsereturn?false; }

結(jié)構(gòu)體和數(shù)組也可以作為函數(shù)的參數(shù)。如果是數(shù)組作為函數(shù)的參數(shù),則必須制定其大小。在調(diào)用傳參時,只傳數(shù)組名就可以了。

vec4?sumVectors(int?sumSize,?vec4?v[10]);void?main() {vec4?myColors[10];...vec4?sumColor?=?sumVectors(5,?myColors); }vec4?sumVectors(int?sumSize,?vec4?v[10]) {int?i?=?0;vec4?sum?=?vec4(0.0);for(;?i?<?sumSize;?++i){sum?+=?v[i];?}return?sum; }

GLSL的函數(shù)是支持重載的。函數(shù)可以同名但其參數(shù)類型或者參數(shù)個數(shù)不同即可。

float?sum(float?a,?float?b) {return?a?+?b; }vec3?sum(vec3?v1,?vec3?v2) {return?v1?+?v2; }

總結(jié)

以上是生活随笔為你收集整理的glsl基础的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。