GLSL

OpenGL Shading Language (GLSL)
GLSL
文章图片


GLSL
文章图片


1.数据类型

作为一种着色语言,GLSL是纯粹地和GPU打交道的计算机语言。因为GPU是多线程并行处理器,所以GLSL直接面向并行模型的多线程计算。用GLSL编写的着色器函数是对每个数据同时执行的。也就是说,每个vertex都会由vertex render的算法处理,每个fragment也都会由fragment rener的算法处理。因此,初学者在编写自己的着色器时,需要考虑到并发特性,并用并行计算的思路来思考问题.

GLSL有三种基本数据类型:float,int和bool,以及由这些数据类型组成的数组和结构体。GLSL并不支持指针GLSL将向量和矩阵作为基本数据类型,这也是所有着色语言的特点之一,因为它们极大地方便了线性代数运算。向量类型包括由上述三种基本数据类型构成的二维、三维和四维的向量,矩阵类型包括浮点型的2×2、3×3和4×4的方阵。比如,浮点型三维向量类型为vec3,整形四维向量类型为ivec4,而3×3的矩阵为mat3。使用以下方法可以声明和使用向量和矩阵:


vec3 v; //声明三维浮点型向量v mat4 m; //声明四维浮点型方阵m v[1]=3.0; //给向量v的第二个元素赋值 m[2][3]=2.0; //给方阵的第三行、第四列元素赋值

除了用索引的方式外,还可以用选择运算符的方式来使用向量。选择运算符是对于向量的各个元素(最多为4个)约定俗成的名称,用一个小写拉丁字母来表示。根据向量表示对象的意义不同,可以使用以下选择运算符:表示顶点位置可以用x、y、z、w;表示颜色可以用r、g、b、a;表示纹理坐标可以用s、t、r、q。用户可以选择其中任意一种选择运算符,它们的作用是等效的。也就是说,如果v是一个向量,那么v[0]、v.r、v.x和v.s都指的是向量v的第一个元素。同时,我们还可以用类似C++构造函数的方式来给向量初始化。下面是用构造函数的方式给向量初始化以及用选择运算符来使用向量的例子:

  1. vec4 v1=vec4(1.0, 2.0, 3.0, 4.0);//用构造函数的方式声明并初始化四维浮点型//向量v1
  2. vec4 v2;
  3. v2.xy=v1.yz; //将v1的第二个和第三个元素复制到v2的第//一个和第二个元素
  4. v2.z=2.0; //给v2的第三个元素赋值
  5. v2.xy=v1.yx; //将v1的头两个元素互换,再复制到v2的头//两个元素中

可以看到,选择运算符给用户提供了一种简洁的方法来对向量的元素进行选择和重排。另外,由于向量和矩阵都是GLSL的基本数据类型,因此在同类型数据复制时不需要指针。
2.限定符variable qualifiers const限定符和C/C++里的相同,表示限定的变量在编译时不可被修改,即它标记了一个常量。const限定符是4个限定符中被标记变量不可被更改的范围最大的。其余的三个限定符是GLSL特有的,所以它们都用在着色器内部声明变量。仅能用于顶点着色器。从OpenGL应用程序向顶点着色器中传递参数.

attribute限定符标记的是一种全局变量,该变量对于某一顶点来说是不可更改的,attribute标记的变量在顶点着色器中是只读(read-only)的。

uniform限定符也标记了一种全局变量,该变量对于一个图元(primitive)来说是不可更改的。先来解释图元的含义,它包括两种类型。首先,图元是指在应用程序中定义的一个完整的几何模型,比如圆、多边形、球体等;其次,它还指离散的像素实体,比如一幅位图。从OpenGL应用程序向顶点着色器中传递参数.,uniform限定符可以用于顶点着色器和像素着色器。在两种着色器内部,uniform变量都是只读的。在着色器中声明uniform变量时可以这样做:


uniform float v_time; void main(void) { //主函数的内容
上面的代码中有一个主函数,也就是说,每个着色器中都会有一个主函数。uniform变量作为全局变量,声明在主函数之前,
GLSL还提供了从顶点着色器向片段着色器传递数据的方法,即使用varying变量。用varying限定符可以在顶点着色器中定义变量,然后再传递给光栅化器,光栅化器对数据插值后,再将每个片段的值交给片段着色器。

3.运算符和数学函数

GLSL支持所有标准的运算符,且这些运算符都同样支持向量和矩阵运算。比如:



mat4 a, b, c; c=a * b; GLSL中的大多数数学函数都对向量和矩阵同样有效。

  1. vec3 a, b;
  2. b=sqrt(a);
b中的每个元素都是a的对应元素的平方根。
GLSL支持所有C的流程控制语句,包括if、for、while以及do-while,用法和C完全相同。这里需要注意的是,循环语句应尽量避免。特别是在使用了比较低端的GPU的时候,过于复杂的流程控制语句执行起来会异常缓慢。这是因为GPU中的处理器的指令缓存较小,且没有分支预测能力。

【GLSL】


    推荐阅读