天天看點

OpenGL ES 變量、結構體、語句、函數、精度

一個

有态度

的程式員

OpenGL ES 變量、結構體、語句、函數、精度

變量

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;           

複制