GLSL ES 概述
GLSL ES 变成语言是在 OpenGL 着色器语言(GLSL)的基础上,删除和简化一部分功能后形成的。GLSL ES 的目标平台是消费电子产品或嵌入式设备;因此简化 GLSL ES 能够允许硬件厂商对这些设备的硬件进行简化,由此带来的好处是降低了硬件的功耗,以及更重要的,减少了性能开销。
#基础
编写规范:
- 程序是大小写敏感的;
- 每一个语句都应该以一个英文分号结束;
#执行次序
从 main() 函数开始执行,着色器程序必须有且仅有一个 main() 函数,而且该函数不能接收任何参数。main() 函数前面的 void 关键字表示这个函数不返回任何值。
#注释
在着色器程序中,可以添加注释,而且注释的格式和 JavaScript 中的注释格式是相同的:
- 单行注释:// 后直到换行处的所有字符为注释
int kep // 注释
- 多行注释:/* 和 */ 之间的所有字符为注释
#数据值类型(数值和布尔值)
GLSL 支持两种数据值类型
- 数值类型:GLSL ES 支持整型数和浮点数,没有小数点的值被认为是整型数,而有小数点的值被称为浮点数。
- 布尔值类型:包含 true 和 false
#变量
组合规则:
- 只包括 a-z、A-Z,0-9 和下划线。
- 变量名的首字母不能是数字。
- 不能以 gl_、webgl_ 或 webgl 开头,这些前缀是 OpenGL ES 保留字
- 不能是下表所列出的关键字,也不能是那些保留字。但是,你的变量名的一部分可以是他们。
#GLSL ES 是强类型语言
GLSL ES 不像 JavaScript,他必须具体地指明变量的数据类型。
#基本类型
GLSL ES 支持的基本类型如下:
类型描述float单精度浮点数类型,该类型的变量表示一个单精度浮点数int整型数,该类型的变量表示一个整数bool布尔值,该类型的变量表示一个布尔值
下面代码是声明基本类型的变量例子:
float klimt; // 变量为一个浮点数
int utrillo; // 变量为一个整型数
bool doga; // 变量为一个布尔值
#赋值和类型转换
使用等号可以进行赋值,两侧类型需要一致:
int i = 8;
float f1= 9; // 错误
float f2 = 9.0; // 没问题
要将一个整型数值赋值给浮点型变量,需要将整型数转换为浮点数,这个过程称为类型转换,比如,可以使用内置的函数 float() 来将整型数转换为浮点数:
int i = 8;
float f1= float(i); // 将 8 转换为 8.0 并赋值给 f1
GLSL ES 支持下面几种类型转换的内置函数:
#运算符
#矢量和矩阵
GLSL ES 支持矢量和矩阵类型,这两种数据类型很适合用来处理计算机图形。矢量和矩阵类型的变量都包含多个元素,每个元素是一个数值(整型数、浮点数或布尔值)。矢量将这些元素排成一列,可以用来表示顶点坐标或颜色值等,而矩阵则将元素划分成行和列,可以用来表示变换矩阵。图给出了矢量和矩阵的例子。
GLSL ES 支持多种不同的矢量和矩阵类型,
类别GLSL ES 数据类型描述矢量vec2、vec3、vec4
ivec2、ivec3、ivec4
bvec2、bvec3、bvec4具有 2、3、4 个浮点数元素的矢量
具有 2、3、4 个整行数元素的矢量
具有 2、3、4 个布尔值元素的矢量矩阵mat2、mat3、mat42 × 2、3 × 3、4 × 4 的浮点数元素的矩阵(分别具有4、9、16 个元素)
#赋值和构造
同样适用等号来对矢量和矩阵进行赋值操作。通常我们使用与数据类型同名的内置构造函数来生成变量,对于 vec4 类型来说,就可以使用内置的 vec4() 函数。如下:
vec4 position = new vec4(1.0, 2.0, 3.0, 4.0);
#矢量构造函数
在 GLSL ES 中,矢量非常重要,所以 GLSL ES 提供了丰富灵活的方式来创建矢量如:
vec3 v3 = vec3(1.0, 0.0, 0.5); // 将 v3 设为(1.0, 0.0, 0.5)
vec2 v2 = vec2(v3); // 使用 v3 的前两个元素,将 v2 设为 (1.0, 0.0)
vec4 v4 = vec4(1.0); // 将 v4 设为 (1.0, 1.0, 1.0, 1.0)
如果构造函数接收了不止一个参数,但是参数的个数又比矢量的元素个数少,就会出错:
也可以将多个矢量组合成一个矢量:
vec4 v4 = vec4(v2, v4); // 将 v4 设为 (1.0, 0.0, 1.0, 1.0)
上面的填充规则是,先把第一个参数 v2 的所有元素填充进去,如果还未填满,就继续用第 2 个参数 v4 中的元素填充。
#矩阵构造函数
矩阵构造函数的使用方式与矢量构造函数的使用方式类似。但是,要保证存储在矩阵中的元素是按照列主序排列的,如下结果例子:
- 向矩阵构造函数中传入矩阵的每一个元素的数值类构造矩阵,注意传入值的顺序必须是列主序的。
vec4 m4 = mat4(1.0, 2.0, 3.0, 4.0,
5.0, 6.0, 7.0, 8.0,
9.0, 10.0, 11.0, 12.0,
13.0, 14.0, 15.0, 16.0);
- 向矩阵构造函数中传入一个或多个矢量,按照列主序使用矢量里的元素值来构造矩阵。
// 使用两个 vec2 对象来创建 mat2 对象
vec2 v2_1 = vec2(1.0, 3.0);
vec2 v2_2 = vec2(2.0, 4.0);
mat2 m2_1 = mat2(v2_1, v2_2); // 1.0, 2.0
// 3.0, 4.0
// 使用一个 vec4 对象来创建 mat2 对象
vec4 v4 = vec4(1.0, 3.0, 2.0, 4.0);
mat2 m2_2 = mat2(v4); // 1.0, 2.0
// 3.0, 4.0
- 向矩阵构造函数中传入矢量和数值,按照列主序使用矢量里的元素和直接传入的数值类构造矩阵。
mat2 m2 = mat2(1.0, 3.0, v2_2); // 1.0, 2.0
// 3.0, 4.0
- 向矩阵构造函数中传入单个数值,这样将生成一个对角线上元素都是该数值,其他元素为 0.0 的矩阵。
mat4 m4 = mat4(1.0); // 1.0, 0.0, 0.0, 0.0
// 0.0, 1.0, 0.0, 0.0
// 0.0, 0.0, 1.0, 0.0
// 0.0, 1.0, 0.0, 1.0
如果传入的数值数量大于 1,又没有达到矩阵元素的数量,就会出错。
#访问元素
访问矢量或矩阵中的元素,可以使用 . 或者 [] 运算符。
#运算符
在矢量变量名后接点运算符,然后接上分量名,就可以访问矢量的元素了。矢量的分量名如下:
类别描述x,y,z,w用来获取顶点坐标分量r,g,b,a用来获取颜色分量s,t,p,g用来获取纹理坐标分量
由于矢量可以用来存储顶点的坐标、颜色和纹理坐标,所以 GLSL ES 支持以上三种分量名称以增强程序的可读性。事实上,任何矢量的 x、r 或 s 分量都会返回第1个分量 y、g、t 分量都返回第2个分量,等等。如果你愿意,你可以随意地交换使用它们。比如:
vec3 v3 = vec3(1,0,2.0,3.0); // 将V3设为(1,0,2.0,3.0)
float f:
f = v3,x; // 设 f 为1,0
f = v3.y; // 设 f 为2,0
f = v3.z; // 设 f 为3.0
f = v3.r // 设 f 为1,0
f = v3.s; // 设 f 为1.0
如你所见,在这些例子中 x、r 和 s 虽然名称不同,但访问的却都是第1个分量。如果试图访问超过矢量长度的分量,就会出错:
f = v3.w; // v3 变量中不存在的第4个元素,w 无法访问
将(同一个集合的)多个分量名共同置于点运算符后,就可以从矢量中同时抽取出多个分量。这个过程称作混合( swizzling)。在下面这个例子中,我们使用了 x、y、z 和 w,其他的集合也有相同的效果:
vec2 v2
v2 = v3.xy; // 设 v2 为(1,0, 2.0)
v2 = V3.yz; // 设 v2 为(2.0, 3,0) 可以省略任意分量
v2 = v3.xz; // 设 v2 为(1.0, 3.0) 可以跳过任意分量
v2 = v3.yx; // 设 v2 为(2.0, 2.0) 可以逆序
v2 = v3.xx; // 设 v2 为(1.0, 1.0) 可以重复任意分量
vec3 v3a;
v3a = v3.zyx; // 设 v3a 为(3.0, 2.0, 1.0) 可以使用所有分量
聚合分量名也可以用来作为赋值表达式 (=) 的左值:
vec4 = position = vec4(1.0, 2.0, 3.0, 4.0);
position.xw = vec2(5.0, 6.0); // position = (5.0, 2.0, 3.0, 6.0)
记住,此时的多个分量名必须属于同一个集合,比如说,你不能使用 v3.was
本文暂时没有评论,来添加一个吧(●'◡'●)