OpenGL ES 3.0學習實踐
- android平臺下OpenGL ES 3.0從零開始
- android平臺下OpenGL ES 3.0繪制純色背景
- android平臺下OpenGL ES 3.0繪制圓點、直線和三角形
- android平臺下OpenGL ES 3.0繪制彩色三角形
- android平臺下OpenGL ES 3.0從矩形中看矩陣和正交投影
- android平臺下OpenGL ES 3.0著色語言基礎知識(上)
- android平臺下OpenGL ES 3.0著色語言基礎知識(下)
- android平臺下OpenGL ES 3.0實例詳解頂點屬性、頂點數組
- android平臺下OpenGL ES 3.0實例詳解頂點緩沖區對象(VBO)和頂點數組對象(VAO)
- android平臺下OpenGLES3.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版》