1 GLSL的基本数据类型

GLSL中支持以下基本数据类型:

类型 描述
float 32位浮点值
double 64位浮点值
int 有符号32位整型
uint 无符号32位整型
bool 布尔值

2 GLSL的聚合类型:向量和矩阵

GLSL的基本类型可以进行合并,从而与核心OpenGL的数据类型相匹配以及可以简化计算过程。
GLSL支持2个、3个、4个分量的向量,每个分量都可以使用float、int、bool、uint、double等基本数据类型。除了向量之外,GLSL也支持float和doublel类型的矩阵。

基本类型 2D向量 3D向量 4D向量 矩阵类型
float vec2 vec3 vec4 mat2 mat3 mat4 mat2x2 mat2x3 mat2x4 mat3x2 mat3x3 mat3x4 mat4x2 mat4x3 mat4x4
double dvec2 dvec3 dvec4 dmat2 dmat3 dmat4 dmat2x2 dmat2x3 dmat2x4 dmat3x2 dmat3x3 dmat3x4 dmat4x2 dmat4x3 dmat4x4
int ivec2 ivec3 ivec4
uint uvec2 uvec3 uvec4
bool bvec2 bvec3 bvec4

2.1 向量

2.1.1 向量初始化

2.1.1.1 向量初始化
vec3 color = vec3(0.3,0.5,0.6);

而相同类型之间也可以进行等价转化:

vec3 color = vec3(0.3,0.5,0.6);
vec3 colorCopy = vec3(color);
2.1.1.2 向量构造函数的截短

向量的构造函数可以截短或者加长一个向量。比如一个较长向量传递给一个较短的向量的构造函数,那么向量会被自动截取到短向量的长度。

vec4 color = vec4(1.0,0.0,0.9,1.0);
vec3 color3 = vec3(color);

此时color3的值为:

(1.0,0.0,0.9)
2.1.1.3 向量构造函数的加长

我们也可以使用一个较短的向量加长得到较长的向量

vec3 color = vec3(1.0,0.0,0.2);
vec4 color4 = (color,1.0);

此时color4的值为:

(1.0,0.0,0.2,1.0)

2.1.2 向量元素的访问

向量元素的访问支持使用分量的名称和数组访问的形式。

2.1.2.1 使用分量名称进行访问
vec3 color = vec3(1.0,0.5,0.5);
float red = color.r;
float green = color.g;
float blue = color.b;

分量名称的组合共有三种形式,不同名称的集合只是为了在使用时便于区分不同的操作。
三种形式如下表:

符号描述 分量访问符
与位置有关的分量 (x,y,z,w)
与颜色有关的分量 (r,g,b,a)
与纹理坐标有关的分量 (s,t,p,q)

需要注意的点:

  • 在一条语句的一个变量中,只能使用一种类型的访问符,也就是说以下的代码是错误的。
vec4 color = colorCopy.rgz;
// z为位置有关的分量
  • 使用分量访问元素时不能超出变量类型的范围
vec2 color;
float blue = color.b;

出错,因为是2维向量没有b分量。

  • 反转分量
vec3 color = colorCopy.argb;

将透明分量a放在第一个元素值,然后是rgb

2.1.2.2 数组访问
vec3 color = vec3(1.0,0.5,0.5);
float red = color[0];
float green = color[1];
float blue = color[2];

2.1.3 向量的长度

向量的长度可以通过length()方法返回向量包含分量的个数。

2.2 矩阵

2.2.1 矩阵的维度

mat3x4,第一个数值代表列数,第二个数值代表行数,mat3x4表示这是一个3列4行的矩阵。

2.2.2 矩阵的初始化

2.2.2.1 初始矩阵为对角矩阵
mat3 tempMat = mat3(2.0);

此时:

tempMat=\begin{bmatrix}2.0&0.0&0.0\\0.0&2.0&0.0\\0.0&0.0&2.0\end{bmatrix}
2.2.2.2 指定矩阵每一个元素的值构建矩阵

传入的矩阵元素可以是标量和向量的集合,只需要将所有的元素值都填充。另外矩阵的指定需要遵循列主序的原则,传入的数据必须首先填充列然后再填充行,这一点与C语言中二维数组的初始化是相反的。

  • 使用所有元素值初始化矩阵
mat3 M = mat3(1.0,2.0,3.0,
1.0,3.0,2.0,
0.0,2.0,1.0);
  • 使用列向量初始化矩阵

方式1:

vec3 column1 = vec3(1.0,2.0,3.0);
vec3 column2 = vec3(1.0,3.0,2.0);
vec3 column3 = vec3(0.0,2.0,1.0);
mat3 M = mat3(column1,column2,column3);

方式2:

vec2 column1 = vec2(1.0,2.0);
vec2 column2 = vec2(1.0,3.0);
vec3 column3 = vec(0.0,2.0);
mat3 M = mat3(column1,3.0,
column2,2.0,
column3,1.0);

2.2.3 矩阵元素的访问

矩阵元素的访问可以使用数组标记的方式,直接从矩阵中得到一个标量值或者一组元素值。

  • 获取元素标量值
float value = mat[1][1]; // 获取第一列第一行的元素值
  • 获取一组元素值
vec3 vec = mat[2]; // 获取矩阵的第三列

2.2.4 矩阵的长度

矩阵的length()方法返回的是它包含列的个数。而行的个数可以通过列的长度length()方法进行返回。

mat3x3 mat;

// 列数
int columeNum = mat.length();

// 行数
int rowNum = mat[0].length(); //通过第1列的长度返回矩阵的行数

3 数组

3.1 数组的声明

GLSL还支持任意类型的数组,包括结构体数组。

和C语言相同,数组的所以可以通过方括号[]来完成。和C语言类似,一个大小为n的数组的元素范围为0到n-1。负数形式的数组索引值,或者超出范围的索引值都是不允许的。

数组可以定义为有大小的,或者没有大小的。我们可以使用没有大小的数组作为一个数组变量的前置声明,然后重新用一个合适的大小来声明它。数组形式的声明需要使用方括号[]。

例如下面两种声明的的作用是一样的:

float color[3];
float[3] color;

另外可以声明未定义维数的数组作为前置声明:

int length[];

3.2 数组初始化

float color[3]=float[3]{1.0,0.0,1.0};

其中构造函数的维数值可以不需要填。

3.3 数组的长度

我们可以使用length方法返回数组元素的个数,例如

int length = color.length();

3.4 数组的遍历

for(int i=0;i<color.length();++i)
{
    float value = color[i];
}

4 结构体

和C语言一样,可以使用结构体struct将不同数据类型的变量组合到一个结构体中。结构有利于组织自定义数据,并可以简化多组数据传入到函数的过程。

4.1 结构体的声明

struct MyStruct
{
    float red ;
    vec3 position;
    vec3 dir;
}

4.2 结构体初始化

vec3 positionValue = vec3(200.0,30.0,300.0);
vec3 dirValue = vec3(-1,1,0);
MyStruct tempStruct = MyStruct{20.0f,positionValue,dirValue};