Modern OpenGL – GLSL着色语言3:GLSL中的数据类型
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);
此时:
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};
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:Modern OpenGL – GLSL着色语言3:GLSL中的数据类型
原文链接:https://www.stubbornhuang.com/996/
发布于:2020年11月24日 22:14:36
修改于:2023年06月26日 22:04:49
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论
52