语言组成:标量,向量,矩阵,采样器,结构体,数组
类型 | 说明 |
---|---|
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位精度。
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(片元着色器)之间传递变量 |
1.const:
被const限定符修饰的变量初始后不可变,出了局部变量,函数参数也可以使用const修饰符。结构变量可以用const修饰,但结构中的字段不行。
const变量必须在声明时就初始化
const vec3 v=vec3(0.0,0.0,0.0);
局部变量只能使用const限定符;函数参数只能使用const限定符。
2.attribute:
attribute变量是全局只读的,它只能在vertext shader中使用,只能与浮点数,向量或矩阵变量组合,一般attribute变量用来防止程序传递来的模型顶点,法线,颜色,纹理等数据,它可以访问数据缓冲区。
attribute vec4 a_Position;
3.uniform:
uniform变量是全局且只读的,在整个shader执行完毕前其值不会改变,它可以和任意基本类型变量组合,一般我们使用uniform变量来放置外部程序传递来的环境数据(如光源位置,模型的变换矩阵等等),这些数据在运行中显然不需要被改变。
uniform vec4 lightPosition;
4.varying:
varying变量是vertex shader与fragment shader之间的信使,一般在vertex shader中修改然后在fragment shader使用它,但不能在fragment shader中修改它。
//顶点着色器
varying vec4 v_Color;
void main(){
...
v_Color = vec4(1.,1.,1.,1);
}
//片元着色器
...
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
...
要注意全局变量限制符只能为 const、attribute、uniform和varying中的一个.不可复合.