老
孟
一個
有态度
的程式員

變量
void
表示空,用于無傳回值的函數。比如頂點shader中main函數:
void main() {
gl_Position = vPosition;
}
複制
float、int、bool
分别代表浮點型,整型,布爾型。定義各類型變量如下:
float f = 1.0;
int i =0;
bool b = true;
複制
vec2、vec3、vec4
分别包含2、3、4個float類型的向量。定義變量如下:
vec2 v2 = vec2(1.0, 0.0);
vec3 v3 = vec3(1.0, 0.0, 0.5);
vec4 v4 = vec4(1.0, 0.0, 0.5,0.5);
複制
如果隻給一個參數,則向量中其他值也會使用此值,比如給vec4一個1.0的值:
vec4 v5 = vec4(1.0);
複制
等價于:
vec4 v5 = vec4(1.0,1.0,1.0,1.0);
複制
注意:提供給向量的參數隻能是1個或者對應向量個數,比如vec4類型不能提供2個參數:
vec4 v6 = vec4(1.0,1.0);
複制
上面給vec4提供2個參數的寫法是錯誤的。
經常使用的内置變量gl_Position和gl_FragColor是vec4類型,在片段shader中設定顔色:
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
複制
ivec2, ivec3, ivec4和vec2、vec3、vec4用法一樣,差別就是ivec的參數是int類型。
bvec2, bvec3, bvec4和vec2、vec3、vec4用法一樣,差別就是bvec的參數是bool類型。
向量分量
擷取向量分量有2種方式:
-
通過 “.” 符号擷取,向量分量為{x, y, z, w} , {r, g, b, a} 或 {s, t, r, q} ,
{x, y, z, w}是位置相關的分量,{r, g, b, a}是顔色相關的分量,{s, t, r, q}是紋理坐标相關的分量,但是(x,y,z,w)、(r,g,b,a)和(s,t,r,q)不能混合使用。
- 通過數組下标擷取,例如v2[0]。
用法如下:
vec4 v4 = vec4(1.0, 0.0, 0.5,0.5);
float a = v4.x;
vec2 v2 = v4.xy;
vec4 v5 = vec4(v4.x,v4.y,v4.z,v4.w);
vec4 color = vec4(v4.r,v4.g,v4.b,v4.a);
複制
mat2, mat3, mat4
分别表示2x2,3x3,4x4浮點型矩陣。如果隻提供一個參數,則該值做為矩陣對角線的值,也就是機關矩陣,比如mat4(1.0),就是4x4機關矩陣。
也可以按照如下方式定義矩陣:
mat3 m3 = mat3(1.0, 0.0, 0.0, // 第一列
0.0, 1.0, 0.0, // 第二列
0.0, 1.0, 1.0); // 第三列
複制
sampler2D、samplerCube、samplerExternalOES
- sampler2D:2D紋理,可以用于繪制圖檔。
- amplerCube:立方體紋理。
- samplerExternalOES:Android端用于繪制視訊或者相機預覽,使用samplerExternalOES需要在shader頭部添加 #extension GL_OES_EGL_image_external : require。
用法如下:
#extension GL_OES_EGL_image_external : require
uniform samplerExternalOES u_Texture;
複制
結構體
在GLSL中允許聲明結構體,和c語言類型,聲明如下:
struct myStruct
{
vec4 color;
vec4 position;
} myVertex;
複制
聲明了一個myStruct類型的變量myVertex。初始化如下:
myVertex = myStruct(vec4(0.0, 1.0, 0.0, 0.0),vec4(0.5, 0.5,0.5, 0.5));
複制
類型要和結構體中一一對應。
擷取結構體值的方式如下:
vec4 color = myVertex.color;
vec4 position = myVertex.position;
複制
基本語句
if-else
if-else 是條件判斷語句,用法如下:
if (color.a < 0.25) {
gl_FragColor = vec4(1,0,0,1);
} else {
gl_FragColor = vec4(1,0,0,color.a);
}
複制
for 循環
使用for循環時,循環變量必須是編譯時已知,用法如下:
float sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
複制
第一種典型的錯誤用法:
float myArr[4];
float sum = 0;
for (int i = 0; i < 3; i++) {
sum += myArr[i];
}
複制
[ ]中隻能為常量或 uniform 變量,不能為整數量變量(如:i,j,k)。
第二種典型的錯誤用法:
uniform int loopIter;
for (int i = 0; i < loopIter; i++) {
sum += i;
}
複制
上面的用法是錯誤的,循環變量 loopIter 的值必須是編譯時已知。
函數
函數的用法和C語言基本相同,在GLSL中不能遞歸調用且必須聲明傳回值類型,如果沒有傳回值則使用void。用法如下:
vec4 getPosition(float a){
return vec4(0.0,0.0,0.0,a);
}
void main(){
}
複制
精度限定符
在GLSL中精度限定符分為低(lowp)、中(mediump)、高(highp)精度。當使用低精度時可以更加高效的運作,如果精度不合理可能會出現失真的問題,曾經在項目中遇到過拍照黑邊的問題就是精度的問題引起的。
指定預設精度方式如下:
precision mediump float;
複制
如果未使用的精度限定符的變量将會使用此預設值,用法如下:
//指定精度
highp vec4 position;
//預設精度
vec4 color;
複制