一.概述
GLSL(OpenGL着色器语言)在OpenGL2.x以上的可渲染管道编程中,非常重要。在之前固定管线里面的很多方法在OpenGL2.x以上不再存在的原因,就是因为其可移植到GLSL里面,这样可以降低硬件功耗,减少性能开销。
二.基本语法规则
- 大小写敏感
- 语句末尾 必须 要有分号
- 从main函数开始执行
- 函数声明中 不能省略返回值类型 (无返回值就是void,C语言可以省略,但这里不行)
- 注释语法和C语言一致(单行//,多行/**/)
三.变量和基本数据类型
1.基本数据类型
只支持2种基本数据类型:
- 数值类型:整数,浮点数
- 布尔类型:true和false2个布尔常量
注意 :不支持字符串
2.变量
变量声明
和C语言一样,类型+变量名,变量命名规则也一样,基本类型只有int、float和bool类型转换
没有 隐式类型转换,也 不支持 3f 这样的类型后缀,但提供了类型转换函数:int()、float()和bool(),都只接受其余2种基本数据类型- 运算符
不支持位运算,其它和C语言一致,也支持3目选择,逻辑与(&&)和逻辑或(||)也有短路特性 - 作用域
与C语言一致,函数内部声明的是局部变量,外面声明的就是全局变量
四.复杂数据类型
1.矢量(vec)
支持2、3、4维矢量,按分量数据类型分为3类:
vec2、vec3、vec4:分量是浮点数
ivec2、ivec3、ivec4:分量是整数
bvec2、bvec3、bvec4:分量是布尔值
构造函数名 和类型名一致,比如 vec4(1.0) 返回4维向量 [1.0, 1.0, 1.0, 1.0] ,如果像这样只传入一个参数,会把所有分量都赋值为该值,如果传入的参数不止一个但比需要的参数数目少,就会 报错 。例如, vec4(1.0)和vec4(1.0, 1.0, 1.0, 1.0) 都没问题,而 vec4(1.0, 1.0)和vec4(1.0, 1.0, 1.0) 就会报错
此外,还可以传入矢量来构造新矢量,或者用现有矢量组合出新矢量,例如:
vec3 v3 = vec3(0.0, 0.5, 1.0); // [0.0, 0.5, 1.0]
vec2 v2 = vec2(v3); // [0.0, 0.5],截取v3的前两个分量
vec4 v4 = vec4(v2, vec4(1.5)); // [0.0, 0.5, 1.5, 1.5],组合v2和新矢量[1.5, 1.5, 1.5, 1.5]
总之,参数可以来自基本值也可以来自其它矢量,但如果参数数量不够且数量不为1就 报错
访问矢量的分量有2种方式,如下:
v4 = vec4(1, 2, 3, 4);
// .分量名
v4.x, v4.y, v4.z, v4.w // 齐次坐标
v4.r, v4.g, v4.b, v4.a // 色值
v4.s, v4.t, v4.p, v4.q // 纹理坐标
// []运算符
v4[0], v4[1], v4[2], v4[3]
点号分量名方式只是为了添上语义,等价于方括号运算符,可以理解为别名,例如 v4[0] 的别名是 v4.x 、 v4.r 以及 v4.s 。更有趣的是,还可以组合使用,比如 v4.xz 返回的2维向量,但此时分量名不能混用( v4.sz 是不对的)
注意 :方括号中的值必须是 常量索引值 ,要么是整数字面量,要么是const修饰的变量、循环索引(流程控制部分再解释),或者这3者组成的表达式
2.矩阵(mat)
只支持2、3、4维 方阵 ,只支持浮点数类型分量:mat2、mat3、mat4
特别注意 :矩阵元素是 列主序 的,例如:
mat4 m4 = mat4(