OpenGL ES 变量、结构体、语句、函数、精度

时间:2022-07-24
本文章向大家介绍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;