android平臺下OpenGL ES 3.0著色語言基礎知識(上)

OpenGL ES 3.0學習實踐

本篇整理自《OpenGL ES 3.0 編程指南第2版》

著色器版本規范

OpenGL ES 3.0 頂點著色器片段著色器的第1行總是聲明著色器版本。聲明著色器版本通知著色器編譯器預期在著色器中出現的語法和結構。編譯器按照聲明的著色語言版本檢查著色器語法。采用如下語法聲明著色器使用OpenGL ES著色語言3.00版本:

#version 300 es

沒有聲明版本號的著色器被認定為使用OpenGL ES著色語言的1.00版本。著色語言的1.00版本用于OpenGLES2.0。對于OpenGLES3.0,作者決定匹配API和著色語言的版本號,這就是版本號從1.00跳到3.00的原因。

變量和變量類型

在計算機圖形中,兩個基本數據類型組成了變換的基礎:向量和矩陣。這兩種數據類型 在OpenGLES著色語言中也是核心。

OpenGLES著色語言中的數據類型

變置分類 類 型 描 述
標量 float,int,uint,bool 用于浮點、整數、無符號整數和布爾值的基于標標量的數據類型
浮點向量 float,vec2,vec3,vec4 有1、2、3、4個分量的基于浮點的向量類型
整數向量 int,ivec2,ivec3,ivec4 有1、2、3、4個分量的基于整數的向量類型
無符號整數向量 uint,uvec2,uvec3,uvec4 有1、2、3、4個分量的基于無符號整數的向量類型
布爾向量 bool,bvec2,bvec3,bvec4, 有1、2.3、4個分量的基于布爾的向量類型
矩陣 mat2(或mat2x2),mat2x3,2x2,2x3,2x4,3x2,3x3,3x4,4x2,4x3mat2x4,mat3x2, mat3(或mat3x3),mat3x4,mat4x2,mat4x3,mat4(或mat4x4)

著色語言中的變量必須以某個類型聲明。例如,下面的聲明描述如何聲明一個標量、一 個向量和一個矩陣

vec4 vPosition;
mat4 mMatirx;
vec2 vOffset;

變量可以在聲明時或者聲明以后初始化。初始化通過使用構造器進行,構造器也用于類
型轉換。

變量構造器

OpenGLES著色語言在類型轉換方面有非常嚴格的規則。也就是說變量只能陚值為相同類型的其他變量或者與相同類型的變量進行運算。

來看看如何使用構造器初始化和轉換標量值。

float myFloat = 1.0;
float myFloat2 = 1; //ERROR: 整數類型轉換浮點類型錯誤
bool myBool = true;
int mylnt = 0;
int mylnt2 = 0.0; // ERROR: 浮點類型轉換整數類型錯誤
myFloat =   float(myBool);  //  布爾值轉換為浮點型
myFloat =   float(mylnt);   //  整型轉換為浮點型
myBool =    bool(mylnt);    //  整型轉換為布爾值

構造器可以用于轉換和初始化向量數據類型。向量構造器的參數將被轉換為與被構造的向量相同的基本類型(float、int或bool)。向量構造器的參數傳遞有兩種基本方法:

  • 如果只為向量構造器提供一個標量參數,則該值用于設置向量的所有值。
  • 如果提供了多個標量或者向量參數,則向量的值從左到右使用這些參數設置。如果提供了多個標量參數,那么在向量中必須有至少和參數中一樣多的分量。

構造向量的例子:

vec4 myVec4 = vec4(1.0);    // myVec4 = {l.0, 1.0, 1.0, 1.0}
vec3 myVec3 = vec3(1.0,0.0,0.5);// myVec3 = {1.0, 0.0, 0.5}
vec3 temp = vec3(myVec3); // temp = myVec3
vec2 myVec2 = vec2(myVec3); // myVec2 = {myVec3.x,myVec3.y}
myVec4 = vec4(myVec2, temp); //myVec4 ? {myVec2.x,myVec2.y,temp.x,temp.y}

下面是構造矩陣的一些基本規則:

  • 如果只為矩陣構造器提供一個標量參數,則該值被放在矩陣的對角線上。例如:mat4(1.0)將創建一個4 x 4的單位矩陣。
  • 矩陣可以從多個向量參數構造。例如: mat2可以從兩個vec2構造
  • 矩陣可以從多個標量參數構造一每個參數代表矩陣中的一個值,從左到右使用。矩陣的構造比剛才說明的基本規則更靈活,只要在矩陣初始化時提供足夠多的分量,矩陣基本上可以從任何標量和向量的組合構造。OpenGLES中的矩陣以列優先順序存儲。使用矩陣構造器時,參數按列填充矩陣。
mat3 myMat3 = mat3(1.0, 0.0, 0.0,    //第一列
                   0.0, 1.0, 0.0,    //第二列
                   0.0, 1.0, 1.0);//第三列

向量和矩陣分量

向量的單獨分量可以用兩種方式訪問:

使用'.'運算符或者通過數組下標。根據組成向量的分量數,每個分量可以通過使用{x,y,z,w}{r,g,b,a}或者{s,t,p,q}組合訪問。3種不同命名方案的原因是向量可以互換地用于表示數學上的向量、顏色和紋理坐標。

使用運算符時,可以在操作中重新排列向量的分量:

vec3 myVec3 = vec3(0.0, 1.0, 2.0);  // myVec3 = {0.0, 1.0, 2.0}
vec3 temp;
temp    =   myVec3.xyz; //  temp    =   {0.0,   1.0,   2.0}
temp    =   myVec3.xxx; //  temp    =   {0.0,   0.0,   0.0}
temp    =   myVec3.zyx; //  temp    =   {2.0,   1.0,   0.0}

除了'.'運算符之外,向量還可以使用數組下標"[]"運算符訪問。在數組下標中,元素[0]對應于x,元索[1]對應于y,等等。
矩陣被看成由一些向量組成。例如:mat2可以看作兩個vec2,mat3可以看作3個vec3,等等。
對于矩陣,單獨的列可以用數組下標運算符"[]"選擇,然后每個向量可以通過向量訪問行為來訪問。

mat4 myMat4 = mat4(1.0);    // 將對角線初始化為1.0
vec4 myVec4 = myMat4[0]; // 從矩陣中獲取myVec4向量
float m1_1 = myMat4[1][1]; // 在矩陣中獲取 [1][1]處的元素
float m2_2 = myMat4[2][2]; // 在矩陣中獲取 [2][2]處的元素

常量

可以將任何基本類型聲明為常數變量。常數變量是著色器中不變的值。聲明常量時,在聲明中加入const限定符。常數必須在聲明時初始化。

const float zero = 0.0;
const float pi = 3.14159;
const vec4 red = vec4(0.0, 0.0, 1.0);
const mat4 identity = mat4(1.0);

正如在C或者C++中那樣,聲明為const的變量是只讀的,不能在源代碼中修改。

結構

除了使用語言中提供的基本類型之外,還可以和c語言一樣將變量聚合成結構OpenGL ES著色語言中聲明結構的語法如下例所示:

struct fogStruct
{
vec4 color;
float start;
float end;
} fogVar;

上述定義的是一個名為fogStruct的新結構類型和一個新變量fogVar
結構可以用構造器初始化。在定義新的結構類型之后,也用與類型相同的名稱定義一個新的結構構造器。結構中的類型和構造器中的類型必須是一對一的。

struct fogStruct
{
vec4 color;
float start;
float end;
} fogVar;

//構造初始化
fogVar = fogStruct(vec4(0.0, 1.0, 0.0, 0.0), //初始化顏色
                   0.5, //初始化 start
                   2.0); //初始化end

數組

數組的語法與C語言很相似,索引從0開始。數組可以用數組初始化構造器初始化

float a[4] = float[](1.0, 2.0, 3.0, 4.0);
float b[4] = float(4](1.0, 2.0, 3,0, 4.0);
vec2 c[2] = vec2[2](vec2(1.0), vec2(1.0));

函數

函數的聲明方法和C語言中相同。如果函數在定義前使用,則必須提供原型聲明。 OpenGLES著色語言函數和C語言函數的最明顯的不同之處在于函數參數的傳遞方法。 OpenGLES著色語言提供特殊的限定符,定義函數是否可以修改可變參數。

OpenGL ES中也提供了很多內建函數

限定符 描述
in (沒有指定時的默認限定符) 這個限定符指定參數按值傳送,函數不能修改
inout 這個限定符規定變量按照引用傳入函數,如果該值被修改,它將在函數退出后變化
out 這個限定符表示該變量的值不被傳入函數,但在函數返冋時將被修改

注意:函數不能遞歸。GPU沒有堆棧。

控制流語句

OpcnGL ES著色語言中的控制流語句的語法類似于C語言。

if(color.a < 0.25){
    color *= color.a;
}
else{
    color = vec4(0.0);
}

條件語句中測試的表達式求出的必須是一個布爾值。

參考
《OpenGL ES 3.0 編程指南第2版》

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容