GLSL語法及特點(diǎn)(轉(zhuǎn)載)

OpenGL ES 1.x是針對(duì)固定硬件管線的而從OpenGL ES 2.0開始針對(duì)可編程硬件管線。而這其中最重要的就是頂點(diǎn)著色器和片元著色器奸汇,頂點(diǎn)著色器是針對(duì)每個(gè)頂點(diǎn)執(zhí)行一次,用于確定頂點(diǎn)的位置谎砾,將顏色信息或者紋理信息傳遞給片元著色器楞陷,片元著色器是針對(duì)每個(gè)片元送巡,片元我們可以理解為每個(gè)像素摹菠,用于確定每個(gè)片元(像素)的顏色。

本文只是介紹著色器語言本身骗爆,而固定管線和可編程管線這里不做詳細(xì)介紹次氨。

一 GLSL特點(diǎn)

OpenGLES的著色器語言GLSL是一種高級(jí)的圖形化編程語言,其源自應(yīng)用廣泛的C語言摘投。與傳統(tǒng)的C語言不同的是煮寡,它提供了更加豐富的針對(duì)于圖像處理的原生類型,諸如向量犀呼、矩陣之類幸撕。GLSL主要包含以下特性:

GLSL是一種面向過程的語言,和C相同外臂。

GLSL的基本語法與C/C++基本相同坐儿。

它完美的支持向量和矩陣操作。

它是通過限定符操作來管理輸入輸出類型的宋光。

GLSL提供了大量的內(nèi)置函數(shù)來提供豐富的擴(kuò)展功能貌矿。


二 GLSL 基礎(chǔ)

GLSL雖然是基于C/C++的語言,也和他們有很多相似的地方罪佳,但是它和C/C++還是有很多的不同之處的逛漫,比如在GLSL中沒有double、long等類型赘艳,沒有union尽楔、enum、unsigned以及位運(yùn)算等特性第练。

之前文中我們所使用的都是非常簡(jiǎn)單的著色器,沒有使用過GLSL的內(nèi)置函數(shù)玛荞,在后面要有比較復(fù)雜的功能實(shí)現(xiàn)娇掏,我們不可避免的要使用這些內(nèi)置函數(shù)。

下面來看GLSL語言的基礎(chǔ)勋眯。

2.1 基本數(shù)據(jù)類型

GLSL中的數(shù)據(jù)類型主要分為標(biāo)量婴梧、向量、矩陣客蹋、采樣器塞蹭、結(jié)構(gòu)體、數(shù)組讶坯、空類型七種類型番电。如下:

1. 標(biāo)量:

標(biāo)量表示的是只有大小沒有方向的量,在GLSL中標(biāo)量只有bool、int和float三種漱办。對(duì)于int这刷,和C一樣,可以寫為十進(jìn)制(16)娩井、八進(jìn)制(020)或者十六進(jìn)制(0x10)暇屋。對(duì)于標(biāo)量的運(yùn)算,我們最需要注意的是精度洞辣,防止溢出問題咐刨。

2. 向量:

向量我們可以看做是數(shù)組,在GLSL通常用于儲(chǔ)存顏色扬霜、坐標(biāo)等數(shù)據(jù)定鸟,針對(duì)維數(shù),可分為二維畜挥、三維和四維向量仔粥。針對(duì)存儲(chǔ)的標(biāo)量類型,可以分為bool蟹但、int和float躯泰。共有vec2、vec3华糖、vec4麦向,ivec2、ivec3客叉、ivec4诵竭、bvec2、bvec3和bvec4九種類型兼搏,數(shù)組代表維數(shù)卵慰、i表示int類型、b表示bool類型佛呻。需要注意的是裳朋,GLSL中的向量表示豎向量,所以與矩陣相乘進(jìn)行變換時(shí)吓著,矩陣在前鲤嫡,向量在后(與DirectX正好相反)。向量在GPU中由硬件支持運(yùn)算绑莺,比CPU快的多暖眼。

作為顏色向量時(shí),用rgba表示分量纺裁,就如同取數(shù)組的中具體數(shù)據(jù)的索引值诫肠。三維顏色向量就用rgb表示分量。比如對(duì)于顏色向量vec4 color,color[0]和color.r都表示color向量的第一個(gè)值区赵,也就是紅色的分量惭缰。其他相同。

作為位置向量時(shí)笼才,用xyzw表示分量漱受,xyz分別表示xyz坐標(biāo),w表示向量的模骡送。三維坐標(biāo)向量為xyz表示分量昂羡,二維向量為xy表示分量。

作為紋理向量時(shí)摔踱,用stpq表示分量虐先,三維用stp表示分量,二維用st表示分量派敷。

3. 矩陣:

在GLSL中矩陣擁有22蛹批、33、4*4三種類型的矩陣篮愉,分別用mat2腐芍、mat3、mat4表示试躏。我們可以把矩陣看做是一個(gè)二維數(shù)組猪勇,也可以用二維數(shù)組下表的方式取里面具體位置的值。

4.采樣器:

采樣器是專門用來對(duì)紋理進(jìn)行采樣工作的颠蕴,在GLSL中一般來說泣刹,一個(gè)采樣器變量表示一副或者一套紋理貼圖。所謂的紋理貼圖可以理解為我們看到的物體上的皮膚犀被。

5.結(jié)構(gòu)體:

和C語言中的結(jié)構(gòu)體相同椅您,用struct來定義結(jié)構(gòu)體,關(guān)于結(jié)構(gòu)體參考C語言中的結(jié)構(gòu)體寡键。

6.數(shù)組:

數(shù)組知識(shí)也和C中相同掀泳,不同的是數(shù)組聲明時(shí)可以不指定大小,但是建議在不必要的情況下昌腰,還是指定大小的好。

7.空類型:

空類型用void表示膀跌,僅用來聲明不返回任何值得函數(shù)遭商。

float a=1.0;

int b=1;

bool c=true;

vec2 d=vec2(1.0,2.0);

vec3 e=vec3(1.0,2.0,3.0)

vec4 f=vec4(vec3,1.2);

vec4 g=vec4(0.2);? //相當(dāng)于vec(0.2,0.2,0.2,0.2)

vec4 h=vec4(a,a,1.3,a);

mat2 i=mat2(0.1,0.5,1.2,2.4);

mat2 j=mat2(0.8);? //相當(dāng)于mat2(0.8,0.8,0.8,0.8)

mat3 k=mat3(e,e,1.2,1.6,1.8);


2.2 運(yùn)算符

GLSL中的運(yùn)算符有(越靠前,運(yùn)算優(yōu)先級(jí)越高):

索引:[]

前綴自加和自減:++捅伤,–

一元非和邏輯非:~劫流,!

加法和減法:+,-

等于和不等于:==祠汇,仍秤!=

邏輯異或:^^

三元運(yùn)算符號(hào),選擇:可很?:

成員選擇與混合:.

后綴自加和自減:++诗力,–

乘法和除法:*,/

關(guān)系運(yùn)算符:>我抠,<苇本,=,>=菜拓,<=瓣窄,<>

邏輯與:&&

邏輯或:||

賦值預(yù)算:=,+=纳鼎,-=俺夕,*=,/=

2.3 類型轉(zhuǎn)換

GLSL的類型轉(zhuǎn)換與C不同贱鄙。在GLSL中類型不可以自動(dòng)提升劝贸,比如float a=1;就是一種錯(cuò)誤的寫法,必須嚴(yán)格的寫成float a=1.0贰逾,也不可以強(qiáng)制轉(zhuǎn)換悬荣,即float a=(float)1;也是錯(cuò)誤的寫法,但是可以用內(nèi)置函數(shù)來進(jìn)行轉(zhuǎn)換疙剑,如float a=float(1);還有float a=float(true);(true為1.0氯迂,false為0.0)等,值得注意的是言缤,低精度的int不能轉(zhuǎn)換為低精度的float嚼蚀。

2.4 限定符

在之前的博客中也提到了,GLSL中的限定符號(hào)主要有:

attritude:一般用于各個(gè)頂點(diǎn)各不相同的量管挟。如頂點(diǎn)顏色轿曙、坐標(biāo)等。

uniform:一般用于對(duì)于3D物體中所有頂點(diǎn)都相同的量僻孝。比如光源位置导帝,統(tǒng)一變換矩陣等。

varying:表示易變量穿铆,一般用于頂點(diǎn)著色器傳遞到片元著色器的量您单。

const:常量。

限定符與java限定符類似荞雏,放在變量類型之前虐秦,并且只能用于全局變量平酿。在GLSL中,沒有默認(rèn)限定符一說悦陋。

2.5 流程控制

GLSL中的流程控制與C中基本相同蜈彼,主要有:

if(){}、if(){}else{}俺驶、if(){}else if(){}else{}

while(){}和do{}while()

for(;;){}

break和continue


2.6 函數(shù)

GLSL中也可以定義函數(shù)幸逆,定義函數(shù)的方式也與C語言基本相同。函數(shù)的返回值可以是GLSL中的除了采樣器的任意類型痒钝。對(duì)于GLSL中函數(shù)的參數(shù)秉颗,可以用參數(shù)用途修飾符來進(jìn)行修飾,常用修飾符如下:

in:輸入?yún)?shù)送矩,無修飾符時(shí)默認(rèn)為此修飾符蚕甥。

out:輸出參數(shù)。

inout:既可以作為輸入?yún)?shù)栋荸,又可以作為輸出參數(shù)菇怀。

2.7 浮點(diǎn)精度

與頂點(diǎn)著色器不同的是,在片元著色器中使用浮點(diǎn)型時(shí)晌块,必須指定浮點(diǎn)類型的精度爱沟,否則編譯會(huì)報(bào)錯(cuò)。精度有三種匆背,分別為:

lowp:低精度呼伸。8位。

mediump:中精度钝尸。10位括享。

highp:高精度。16位珍促。

不僅僅是float可以制定精度铃辖,其他(除了bool相關(guān))類型也同樣可以,但是int猪叙、采樣器類型并不一定要求指定精度娇斩。加精度的定義如下:

uniform lowp float a=1.0;

varying mediump vec4 c;

當(dāng)然,也可以在片元著色器中設(shè)置默認(rèn)精度穴翩,只需要在片元著色器最上面加上precision <精度> <類型>即可制定某種類型的默認(rèn)精度犬第。其他情況相同的話,精度越高芒帕,畫質(zhì)越好歉嗓,使用的資源也越多。

三 GLSL 內(nèi)建變量

在著色器中我們一般都會(huì)聲明變量來在程序中使用副签,但是著色器中還有一些特殊的變量遥椿,不聲明也可以使用。這些變量叫做內(nèi)建變量淆储。內(nèi)建變量冠场,相當(dāng)于著色器硬件的輸入和輸出點(diǎn),使用者利用這些輸入點(diǎn)輸入之后本砰,就會(huì)看到屏幕上的輸出碴裙。通過輸出點(diǎn)可以知道輸出的某些數(shù)據(jù)內(nèi)容。當(dāng)然点额,實(shí)際上肯定不會(huì)這樣簡(jiǎn)單舔株,這么說只是為了幫助理解。在頂點(diǎn)著色器中的內(nèi)建變量和片元著色器的內(nèi)建變量是不相同的还棱。著色器中的內(nèi)建變量有很多载慈,在此,我們只列出最常用的集中內(nèi)建變量珍手。

頂點(diǎn)著色器的內(nèi)建變量

輸入變量:

gl_Position:頂點(diǎn)坐標(biāo)

gl_PointSize:點(diǎn)的大小办铡,沒有賦值則為默認(rèn)值1,通常設(shè)置繪圖為點(diǎn)繪制才有意義琳要。

片元著色器的內(nèi)建變量

輸入變量:

gl_FragCoord:當(dāng)前片元相對(duì)窗口位置所處的坐標(biāo)寡具。

gl_FragFacing:bool型,表示是否為屬于光柵化生成此片元的對(duì)應(yīng)圖元的正面稚补。

輸出變量:

gl_FragColor:當(dāng)前片元顏色

gl_FragData:vec4類型的數(shù)組童叠。向其寫入的信息,供渲染管線的后繼過程使用课幕。

四 常用內(nèi)置函數(shù)

常見函數(shù)

radians(x):角度轉(zhuǎn)弧度

degrees(x):弧度轉(zhuǎn)角度

sin(x):正弦函數(shù)厦坛,傳入值為弧度。相同的還有cos余弦函數(shù)撰豺、tan正切函數(shù)粪般、asin反正弦、acos反余弦污桦、atan反正切

pow(x,y):xy

exp(x):ex

exp2(x):2x

log(x):logex

log2(x):log2x

sqrt(x):x√

inversesqr(x):1x√

abs(x):取x的絕對(duì)值

sign(x):x>0返回1.0亩歹,x<0返回-1.0,否則返回0.0

ceil(x):返回大于或者等于x的整數(shù)

floor(x):返回小于或者等于x的整數(shù)

fract(x):返回x-floor(x)的值

mod(x,y):取模(求余)

min(x,y):獲取xy中小的那個(gè)

max(x,y):獲取xy中大的那個(gè)

mix(x,y,a):返回x?(1?a)+y?a

step(x,a):x< a返回0.0凡橱,否則返回1.0

smoothstep(x,y,a):a < x返回0.0小作,a>y返回1.0,否則返回0.0-1.0之間平滑的Hermite插值稼钩。

dFdx(p):p在x方向上的偏導(dǎo)數(shù)

dFdy(p):p在y方向上的偏導(dǎo)數(shù)

fwidth(p):p在x和y方向上的偏導(dǎo)數(shù)的絕對(duì)值之和


幾何函數(shù)

length(x):計(jì)算向量x的長度

distance(x,y):返回向量xy之間的距離

dot(x,y):返回向量xy的點(diǎn)積

cross(x,y):返回向量xy的差積

normalize(x):返回與x向量方向相同顾稀,長度為1的向量

矩陣函數(shù)

matrixCompMult(x,y):將矩陣相乘

lessThan(x,y):返回向量xy的各個(gè)分量執(zhí)行x< y的結(jié)果,類似的有g(shù)reaterThan,equal,notEqual

lessThanEqual(x,y):返回向量xy的各個(gè)分量執(zhí)行x<= y的結(jié)果坝撑,類似的有類似的有g(shù)reaterThanEqual

any(bvec x):x有一個(gè)元素為true静秆,則為true

all(bvec x):x所有元素為true粮揉,則返回true,否則返回false

not(bvec x):x所有分量執(zhí)行邏輯非運(yùn)算

紋理采樣函數(shù)

紋理采樣函數(shù)有texture2D抚笔、texture2DProj扶认、texture2DLod、texture2DProjLod殊橙、textureCube辐宾、textureCubeLod及texture3D、texture3DProj膨蛮、texture3DLod叠纹、texture3DProjLod等。

texture表示紋理采樣敞葛,2D表示對(duì)2D紋理采樣誉察,3D表示對(duì)3D紋理采樣

Lod后綴,只適用于頂點(diǎn)著色器采樣

Proj表示紋理坐標(biāo)st會(huì)除以q

紋理采樣函數(shù)中惹谐,3D在OpenGLES2.0并不是絕對(duì)支持冒窍。我們?cè)俅螘簳r(shí)不管3D紋理采樣函數(shù)。重點(diǎn)只對(duì)texture2D函數(shù)進(jìn)行說明豺鼻。texture2D擁有三個(gè)參數(shù)综液,第一個(gè)參數(shù)表示紋理采樣器。第二個(gè)參數(shù)表示紋理坐標(biāo)儒飒,可以是二維谬莹、三維、或者四維桩了。第三個(gè)參數(shù)加入后只能在片元著色器中調(diào)用附帽,且只對(duì)采樣器為mipmap類型紋理時(shí)有效。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末井誉,一起剝皮案震驚了整個(gè)濱河市蕉扮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌颗圣,老刑警劉巖喳钟,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異在岂,居然都是意外死亡奔则,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門蔽午,熙熙樓的掌柜王于貴愁眉苦臉地迎上來易茬,“玉大人,你說我怎么就攤上這事及老〕槔常” “怎么了范抓?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長食铐。 經(jīng)常有香客問我尉咕,道長,這世上最難降的妖魔是什么璃岳? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮悔捶,結(jié)果婚禮上铃慷,老公的妹妹穿的比我還像新娘。我一直安慰自己蜕该,他們只是感情好犁柜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著堂淡,像睡著了一般馋缅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绢淀,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天萤悴,我揣著相機(jī)與錄音,去河邊找鬼皆的。 笑死覆履,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的费薄。 我是一名探鬼主播硝全,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼楞抡!你這毒婦竟也來了伟众?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤召廷,失蹤者是張志新(化名)和其女友劉穎凳厢,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體竞慢,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡数初,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了梗顺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泡孩。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖寺谤,靈堂內(nèi)的尸體忽然破棺而出仑鸥,到底是詐尸還是另有隱情吮播,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布眼俊,位于F島的核電站意狠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏疮胖。R本人自食惡果不足惜环戈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望澎灸。 院中可真熱鬧院塞,春花似錦、人聲如沸性昭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽糜颠。三九已至汹族,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間其兴,已是汗流浹背顶瞒。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留元旬,地道東北人搁拙。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像法绵,于是被迫代替她去往敵國和親箕速。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355