《OpenGL從入門(mén)到放棄05》著色器語(yǔ)言

之前文章:

《OpenGL從入門(mén)到放棄01 》一些基本概念
《OpenGL從入門(mén)到放棄02 》GLSurfaceView和Renderer
《OpenGL從入門(mén)到放棄03 》相機(jī)和視圖
《OpenGL從入門(mén)到放棄04 》畫(huà)一個(gè)長(zhǎng)方形

通過(guò)前面幾篇文章,相信大家已經(jīng)掌握了使用OpenGL繪制三角形和長(zhǎng)方形,還有一些看起來(lái)復(fù)雜一點(diǎn)的圓柱、圓錐,就不再介紹了,大家有興趣的話(huà)自己去發(fā)揮一些。
有疑問(wèn)的點(diǎn)應(yīng)該是著色器語(yǔ)言,所以有了這篇文章。

著色器語(yǔ)言

數(shù)據(jù)類(lèi)型

GLSL中的數(shù)據(jù)類(lèi)型主要分為標(biāo)量、向量、矩陣、采樣器、結(jié)構(gòu)體、數(shù)組、空類(lèi)型七種類(lèi)型:

  • 標(biāo)量:相當(dāng)于java的基本數(shù)據(jù)類(lèi)型,在GLSL中標(biāo)量只有bool、int和float三種。我們最需要注意的是精度,防止溢出問(wèn)題。

  • 向量:向量我們可以看做是數(shù)組,在GLSL通常用于儲(chǔ)存顏色、坐標(biāo)等數(shù)據(jù),針對(duì)維數(shù),可分為二維、三維和四維向量。針對(duì)存儲(chǔ)的標(biāo)量類(lèi)型,可以分為bool、int和float。共有vec2、vec3、vec4,ivec2、ivec3、ivec4、bvec2、bvec3和bvec4九種類(lèi)型,數(shù)字代表維數(shù)、i表示int類(lèi)型、b表示bool類(lèi)型。需要注意的是,GLSL中的向量表示豎向量,所以與矩陣相乘進(jìn)行變換時(shí),矩陣在前,向量在后(與DirectX正好相反)。向量在GPU中由硬件支持運(yùn)算,比CPU快的多。

    1. 作為顏色向量時(shí),用rgba表示分量,就如同取數(shù)組的中具體數(shù)據(jù)的索引值。三維顏色向量就用rgb表示分量。比如對(duì)于顏色向量vec4 color,color[0]和color.r都表示color向量的第一個(gè)值,也就是紅色的分量。其他相同。
    2. 作為位置向量時(shí),用xyzw表示分量,xyz分別表示xyz坐標(biāo),w表示向量的模。三維坐標(biāo)向量為xyz表示分量,二維向量為xy表示分量。
    3. 作為紋理向量時(shí),用stpq表示分量,三維用stp表示分量,二維用st表示分量。
  • 矩陣:在GLSL中矩陣擁有22、33、4*4三種類(lèi)型的矩陣,分別用mat2、mat3、mat4表示。我們可以把矩陣看做是一個(gè)二維數(shù)組,也可以用二維數(shù)組下標(biāo)的方式取里面具體位置的值。

  • 采樣器:sampler2D,采樣器是專(zhuān)門(mén)用來(lái)對(duì)紋理進(jìn)行采樣工作的,一般來(lái)說(shuō),一個(gè)采樣器變量表示一副或者一套紋理貼圖。所謂的紋理貼圖可以理解為我們看到的物體上的皮膚。

  • 結(jié)構(gòu)體:和C語(yǔ)言中的結(jié)構(gòu)體相同,用struct來(lái)定義結(jié)構(gòu)體,關(guān)于結(jié)構(gòu)體參考C語(yǔ)言中的結(jié)構(gòu)體。

  • 數(shù)組:跟C、Java中的數(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);

運(yùn)算符

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

  1. 索引:[]
  2. 前綴自加和自減:++,–
  3. 一元非和邏輯非:~,!
  4. 加法和減法:+,-
  5. 等于和不等于:==,!=
  6. 邏輯異或:^^
  7. 三元運(yùn)算符號(hào),選擇:?:
  8. 成員選擇與混合:.
  9. 后綴自加和自減:++,–
  10. 乘法和除法:*,/
  11. 關(guān)系運(yùn)算符:>,<,=,>=,<=,<>
  12. 邏輯與:&&
  13. 邏輯或:||
  14. 賦值預(yù)算:=,+=,-=,*=,/=

基本和其它語(yǔ)言一致。

限定符

attritude:一般用于各個(gè)頂點(diǎn)各不相同的量。如頂點(diǎn)顏色、坐標(biāo)等。
uniform:一般用于對(duì)于3D物體中所有頂點(diǎn)都相同的量。比如光源位置,統(tǒng)一變換矩陣等。
varying:表示易變量,一般用于頂點(diǎn)著色器傳遞到片元著色器的量。
const:常量。
看下例子:

    // 頂點(diǎn)著色器的腳本
    String vertexShaderCode =
                    "uniform mat4 uMVPMatrix;" +    /接收傳入的轉(zhuǎn)換矩陣
                    "attribute vec4 vPosition;" +      //接收傳入的頂點(diǎn)
                    "attribute vec2 aTexCoord;" +       //接收傳入的頂點(diǎn)紋理位置
                    "varying vec2 vTextureCoord;" +     //增加用于傳遞給片元著色器的紋理位置變量
                    "void main() {" +
                        "gl_Position = uMVPMatrix * vPosition;" +  //矩陣變換計(jì)算之后的位置
                        "vTextureCoord = aTexCoord;" +
                    " }";

浮點(diǎn)精度

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

lowp:低精度。8位。
mediump:中精度。10位。
highp:高精度。16位。

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

uniform lowp float a=1.0;
varying mediump vec4 c;

也可以直接在片元著色器第一行聲明

precision mediump float;  // 聲明float類(lèi)型的精度為中等(精度越高越耗資源)

內(nèi)建變量

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

輸入變量

  1. gl_Position:頂點(diǎn)坐標(biāo)
    在上面代碼段可以看到,直接使用gl_Position,不需要定義或者聲明,
  2. gl_PointSize:點(diǎn)的大小,沒(méi)有賦值則為默認(rèn)值1,通常設(shè)置繪圖為點(diǎn)繪制才有意義。

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

輸入變量

  1. gl_FragCoord:當(dāng)前片元相對(duì)窗口位置所處的坐標(biāo)。
  2. gl_FragFacing:bool型,表示是否為屬于光柵化生成此片元的對(duì)應(yīng)圖元的正面。

加粗是我們常用的內(nèi)建變量

輸出變量

  1. gl_FragColor:當(dāng)前片元顏色
  2. gl_FragData:vec4類(lèi)型的數(shù)組。向其寫(xiě)入的信息,供渲染管線(xiàn)的后繼過(guò)程使用。

函數(shù)

常見(jiàn)函數(shù)

  • radians(x):角度轉(zhuǎn)弧度
  • degrees(x):弧度轉(zhuǎn)角度
  • sin(x):正弦函數(shù),傳入值為弧度。相同的還有cos余弦函數(shù)、tan正切函數(shù)、asin反正弦、acos反余弦、atan反正切
  • pow(x,y):[Math Processing Error]xy
  • exp(x):[Math Processing Error]ex
  • exp2(x):[Math Processing Error]2x
  • log(x):[Math Processing Error]logex
  • log2(x):[Math Processing Error]log2x
  • sqrt(x):[Math Processing Error]x
  • inversesqr(x):[Math Processing Error]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):返回[Math Processing Error]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ù)目前基本沒(méi)怎么用到過(guò),所以沒(méi)有加粗,后面用到再回來(lái)查一下即可

幾何函數(shù)

  • length(x):計(jì)算向量x的長(zhǎng)度
  • distance(x,y):返回向量xy之間的距離
  • dot(x,y):返回向量xy的點(diǎn)積
  • cross(x,y):返回向量xy的差積
  • normalize(x):返回與x向量方向相同,長(zhǎng)度為1的向量

ps:distance 函數(shù)在后面做濾鏡的時(shí)候可能會(huì)用到

矩陣函數(shù)

  • matrixCompMult(x,y):將矩陣相乘
  • lessThan(x,y):返回向量xy的各個(gè)分量執(zhí)行x< y的結(jié)果,類(lèi)似的有g(shù)reaterThan,equal,notEqual
  • lessThanEqual(x,y):返回向量xy的各個(gè)分量執(zhí)行x<= y的結(jié)果,類(lèi)似的有類(lèi)似的有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

texture2D 有2個(gè)參數(shù), 第一個(gè)參數(shù)表示紋理采樣器,(紋理采樣器是片元著色器的內(nèi)置變量)。 第二個(gè)參數(shù)表示紋理坐標(biāo),可以是二維、三維、或者四維(我們需要把紋理坐標(biāo)傳過(guò)去)

認(rèn)真閱讀,可以發(fā)現(xiàn)著色器語(yǔ)言并不復(fù)雜,我們只要掌握幾個(gè)常用的,然后其他等需要的時(shí)候再查一下即可。

下一篇開(kāi)始我們將學(xué)習(xí)比較有意思的紋理和圖片處理,敬請(qǐng)期待吧!

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

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

  • 關(guān)于著色器 著色器是用來(lái)實(shí)現(xiàn)圖像渲染的,用來(lái)替代固定渲染管線(xiàn)的可編程程序。著色器替代了傳統(tǒng)的固定渲染管線(xiàn),可以實(shí)現(xiàn)...
    Oneminute閱讀 1,888評(píng)論 1 2
  • 在OpenGL ES中著色器分為頂點(diǎn)著色器和片元著色器。頂點(diǎn)著色器是針對(duì)每個(gè)頂點(diǎn)執(zhí)行一次,用于確定頂點(diǎn)的位置。片元...
    大臉萌家的大眼萌閱讀 3,217評(píng)論 0 3
  • 1 紋理基礎(chǔ) 紋理是一種結(jié)構(gòu)化的存儲(chǔ)形式(Textures are a structured form of st...
    RichardJieChen閱讀 16,590評(píng)論 0 10
  • 2018年9月3日,這一群小寶在媽媽的帶領(lǐng)下來(lái)到了文昌小學(xué)。陌生的環(huán)境,陌生的校園,可是他們絲毫感覺(jué)不到陌生。 孩...
    文昌許珊珊閱讀 289評(píng)論 0 2
  • 我是一個(gè)80后,作為一個(gè)文學(xué)愛(ài)好者,看了太多80后作家的作品,也閱讀過(guò)我們簡(jiǎn)書(shū)作者的一些類(lèi)似個(gè)人經(jīng)歷的小說(shuō)或者故事...
    賈大俠閱讀 2,204評(píng)論 25 52

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