着色器语言主要特性:
- 着色器语言是一门高级的图形编辑语言和过程语言。
- 顶点着色器和片元着色器使用相同的语言。
- 基于C/C++语法及流程控制,但该语言不支持double,byte,short,long数据类型,取消了union,enum,unsigned以及位运算。
- 完美支持向量与矩阵的各种操作。
- 通过类型限定符来管理输入和输出。
- 拥有大量的内置函数来提供丰富的功能。
语言组成:标量,向量,矩阵,采样器,结构体,数组,空类型
基本类型
类型 | 说明 |
---|---|
void | 空类型,既不返回任何值 |
bool | 布尔类型,true/false(标量) |
int | 带符号的整数 signed integer(标量) |
float | 带符号的浮点数 floating scalar(标量) |
vec2,vec3,vec4 | n维浮点数向量 n-component floating point vector |
bvec2,bvec3,bvec4 | n维布尔向量 boolea vector |
ivec2,ivec3,ivec4 | n维整数向量 signed integer vector |
mat2,mat3,mat4 | 2维(2* 2),3维(3* 3),4维(4*4)浮点数矩阵 float matrix |
sampler2D | 2D纹理 a 2D texture |
sampler3D | 3D纹理 a 3D texture |
samplerCube | 盒纹理 cube mapped texture |
旧版GLSL的int类型的取值范围是16位精度,现在是32位精度了。
GLSL的向量可以看做是同样类型的标量组成,如2维向量表示为v2(x,y),3维向量表示为v3(x,y,z) 向量在着色器语言中,用于存储以及操作颜色,位置,纹理坐标等。
单独访问某个分量的基本语法为<向量名>·<分量名>,如颜色向量color(r,g,b,a),color.r=0.6。
GLSL中,矩阵是按列顺序组织的,一个矩阵可以看做由几个列向量组成。如mat3可以看做3个vec3组成。 对于矩阵的访问,可以将矩阵看成列向量的数组。如,matrix为mat4,访问第二列,使用matrix[1],其值为一个vec4,取得第三列的第二个分量,使用matrix[2][1],其值为float;
采样器,如sampler2D等,其专门用来进行纹理采样的相关操作。一般情况下,一个采样器变量代表一副或一套纹理贴图,采样器变量不能在着色器中初始化,一般情况下采样器变量都用uniform限定符来修饰,从宿主语言中(如java)接受传递进着色器的值。
基本结构和数组
类型 | 说明 |
---|---|
结构 | struct type-name{} 类似C语言的结构体 |
数组 | float foo[3] glsl只支持1维数组,数组可以是结构体成员 |
基本类型间的运算:
GLSL中,没有隐式类型的转换,原则上要求左右两侧表达式(left-value = right-value)的类型必须一致,如果类型不同,必须使用显示转换(使用构造函数转换);
1.float与int
同类型之间直接运算,不同类型需要显示转换。
int a=int(2.0);
float a=float(2)*6.0+2.3;
2.float与vec(向量)/mat(矩阵)
vec,mat其实是由float复合而成的,当他们与float预算时,其实就是每一个分量分别于float进行运算,即逐分量运算。GLSL里大部分涉及vec,mat的运算都是逐分量运算,逐分量运算是线性的,如vec与float运算的结果还是vec。
vec3 v=vec3(1.0,2.0,3.0);
mat3 m=mat3(1.0);
float f=10.0;
vec3 a=f*v; //vec3(10.0,20.0,30.0)
vec3 b=v*f; //vec3(10.0,20.0,30.0)
mat3 c=f*m;; //mat3(10.0)
mat3 d=m*f; //mat3(10.0)
int与vec,mat之间是不可运算的,因为vec和mat中的每一个分量都是float类型的,无法与int逐分量运算。
3.vec与vec(向量与向量)
两向量间的运算必须保证操作数的阶数都相同,即维度相同,否则不能计算。计算方式为两操作数在同位置上的分量分别进行运算,且阶数不变,其本质还是逐分量进行。
vec3 a=vec3(1.0,2.0,3.0);
vec3 b=vec3(0.1,0.2,0.3);
vec3 c=a+b; //vec3(1.1,2.2,3.3)
vec3 d=a*b; //vec3(0.1,0.4,0.9)
4.vec与mat(向量与矩阵)
要保证操作数的阶数相同,且vec与mat只存在乘法运算,且结果为vec(向量)。计算方式和线性代数中的矩阵乘法相同。
vec2 v=vec2(10.0,20.0);
mat2 m=mat2(1.0,2.0,3.0,4.0);
vec2 a=m*v; //vec2((1.0*10.0+3.0*20.0),(2.0*10.0+4.0*20.0)) --vec2(70,100)
vec2 b=v*m //vec2((10.0*1.0+20.0*2.0),(10.0*3.0+20.0*4.0)) --vec2(50,110)
向量与矩阵的乘法规则:
矩阵A,B,C; C=A*B 乘法运算注意事项:
1.A的列数等于B的行数;
2.A的行数为C的行数,B的列数为C的列数;
3.C的第m行第n列元素等于A的第m行的各个元素与B的第n列的对应元素相乘之和 4.mat与mat(矩阵和矩阵)
必须操作数的阶数相同,乘法运算为线性代数运算方式。其余的运算仍然为逐分量运算
mat2 a=mat2(1.0,2.0,3.0,4.0);
mat2 b=mat2(10.0,20.0,30.0,40.0);
mat2 c=a+b;//mat2(11.0,22.0,33.0,44.0);
mat2 d=a*b;//mat2((1.0*10.0+3.0*20.0),(2.0*10.0+4.0*20.0),(1.0*30.0+3.0*40.0),(2.0*30.0+4.0*40.0)) --mat2(70.0,100.0,150.0,220.0)
变量限定符
修饰符 | 说明 |
---|---|
none | (默认的,可省略)本地变量,可读可写,函数的输入参数即是这种类型 |
const | 声明变量或函数的参数为只读类型 |
attribute | 只能存在于vertex shader(顶点着色器)中,一般用于保存顶点或法线数据,他可以在数据缓冲区读取数据 |
uniform | 在运行时shader无法改变uniform变量,一般用来放置程序传递给shader的变换矩阵,从材质,光照参数等等 |
varying | 主要负责在vertex(定点着色器)和fragment(片元着色器)之间传递变量 |
要注意全局变量限制符只能为 const、attribute、uniform和varying中的一个.不可复合