webgl之GLSL

2023/8/24 webgl3D

🌙 GLSL

GLSL全称是 Graphics Library Shader Language (图形库着色器语言),是着色器使用的语言。 它有一些不同于JavaScript的特性,主要目的是为栅格化图形提供常用的计算功能。 GLSL语言结构类似于C语言,支持向量、矩阵、函数等基本数据类型和操作符,同时也支持控制结构、循环结构、条件结构等基本的程序结构。

🌙 变量限定符

限定符赋给变量特殊的含义:

  • const: 用于声明非可写的编译时常量变量
  • attribute:用于经常更改的信息,只可以再顶点着色器中使用
  • uniform:用于不经常更改的信息,用于顶点着色器和片元着色器
  • varying:用于从顶点着色器传递到片段着色器的插值信息

🌙 变量声明

在GLSL中,变量需要先进行声明才能使用,声明方式与C语言相似,如下:

// 声明一个整型变量
int a;
// 声明一个浮点型变量
float b;
// 声明一个vec3类型的变量
vec3 c;
1
2
3
4
5
6

🌙 常量

在GLSL中,可以使用关键字"const"来定义常量。常量的定义必须在函数外部进行,且在编译时就确定其值,不能在运行时修改。常量可以是标量、矢量、矩阵或其他数据类型。例如:

const float PI = 3.14159;
const vec3 GRAVITY = vec3(0.0, -9.8, 0.0);
const mat4 IDENTITY_MATRIX = mat4(1.0);
1
2
3

GLSL中有几种不同类型的常量,包括:

  1. 数值常量:表示数值的常量,可以是整数或浮点数。例如:
    • 整数常量:10, -5, 1000
    • 浮点数常量:3.14, -2.5, 1.0e-6
  2. 布尔常量:表示真或假的常量。只有两个可能的值:true和false。
  3. 字符串常量:由一系列字符组成的常量。在GLSL中,字符串常量需要用双引号括起来。例如:"Hello, World!"
  4. 矢量常量:表示多个数值组成的常量。矢量常量可以是二维、三维或四维的。例如:
    • 二维矢量常量:vec2(1.0, 2.0)
    • 三维矢量常量:vec3(1.0, 2.0, 3.0)
    • 四维矢量常量:vec4(1.0, 2.0, 3.0, 4.0)
  5. 矩阵常量:表示多个矢量组成的常量。矩阵常量可以是2x2、3x3或4x4的。例如:
    • 2x2矩阵常量:mat2(1.0, 2.0, 3.0, 4.0)
    • 3x3矩阵常量:mat3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0)
    • 4x4矩阵常量:mat4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0)

这些常量可以在GLSL程序中使用,并在执行期间保持不变。

🌙 数据类型

数据类型是编程语言中用于定义变量的属性和操作的分类。在GLSL中,常见的数据类型包括:

  1. 基本数据类型:
    • 整数类型:int、uint。
    • 浮点数类型:float、double。
    • 布尔类型:bool。
  2. 向量类型:
    • 2D 向量:vec2。
    • 3D 向量:vec3。
    • 4D 向量:vec4。
  3. 矩阵类型:
    • 2x2 矩阵:mat2。
    • 3x3 矩阵:mat3。
    • 4x4 矩阵:mat4。
  4. 纹理类型: 取样器--用于纹理采样:
    • sampler1D 访问一个一维纹理
    • sampler2D 访问一个二维纹理
    • sampler3D 访问一个三维纹理
    • samplerCube 访问一个立方体纹理
    • sampler1DShadow 访问一个带对比的一维深度纹理
    • sampler2DShadow 访问一个带对比的二维深度纹理
  5. 其他类型:
    • 结构体类型:struct, 结构体可以包含任意基础类型、向量类型、矩阵类型、数组类型和其他结构体类型。
    struct dirlight{
         vec3 direction;
         vec3 color;
    };
    
    1
    2
    3
    4
    • 数组类型:数组大小可以是常量或动态, 包含任意基础类型、向量类型、矩阵类型。
    • 空类型:void。 这些数据类型具有不同的大小、精度和用途,可以根据需求选择适当的类型来存储和操作数据。

🌙 数据类型转换

在GLSL中,数据类型的转换不支持隐士类型转换,需要显示地通过类型函数来转换:

  • 浮点数到整数:
        float f = 3.14;
        int i = int(f); // 使用int()函数显式将浮点数转换为整数
    
    1
    2
  • 整数到浮点数:
  int i = 10;
  float f = float(i); // 使用float()函数显式将整数转换为浮点数
1
2
  • 整数到布尔值:
  int i = 1;
  bool b = bool(i); // 使用bool()函数显式将整数转换为布尔值(非零值转换为true,0转换为false)
1
2

需要注意的是,某些转换可能会导致数据丢失或精度损失,因此需要确保转换后的值的行为和正确性。

🌙 运算符

运算符是用于执行特定操作的符号或符号组合。在GLSL中,常见的运算符包括:

  1. 算术运算符:
    • 加法:+
    • 减法:-
    • 乘法:*
    • 除法:/
    • 取余:%
  2. 关系运算符:
    • 相等:==
    • 不等:!=
    • 大于:>
    • 小于:<
    • 大于等于:>=
    • 小于等于:<=
  3. 逻辑运算符:
    • 逻辑与:&&
    • 逻辑或:||
    • 逻辑非:!
  4. 赋值运算符:
    • 简单赋值:=
    • 加法赋值:+=
    • 减法赋值:-=
    • 乘法赋值:*=
    • 除法赋值:/=
    • 取余赋值:%=
  5. 位运算符:
    • 按位与:&
    • 按位或:|
    • 按位异或:^
    • 左移:<<
    • 右移:>>

这些运算符可以用于执行各种数学、逻辑和位操作,以实现不同的计算和功能。

🌙 控制流

GLSL的控制流 与C++非常类似,可以使用for while以及do-while实现循环,也可以使用ifif-else进行选择

🌙 常用的内置变量

变量output还是input说明
highp vec4 gl_Positionoutput用在顶点着色器,顶点坐标信息
mediump float gl_PointSizeoutput用在顶点着色器,需要绘制点的大小,(只在gl.POINTS模式下有效)
mediump vec4 gl_FragCoord;input用在片元着色器,当前点的位置
bool gl_FrontFacing;input用在片元着色器,是否为正面片元
mediump vec2 gl_PointCoord;input用在片元着色器,经过插值计算后的纹理坐标
mediump vec4 gl_FragColor;output用在片元着色器,此像素点的颜色
mediump vec4 gl_FragData[n]output用在片元着色器,当前片点的颜色,使用glDrawBuffers数据数组

🌙 常见的GLSL内置变量和函数

  • sin(x): 正弦函数。
  • cos(x): 余弦函数。
  • tan(x): 正切函数。
  • asin(x): 反正弦函数。
  • acos(x): 反余弦函数。
  • atan(y, x): 反正切函数,返回角度。
  • pow(x, y): 计算幂。
  • sqrt(x): 计算平方根。
  • length(x): 返回向量的长度。
  • normalize(x): 返回长度为1的向量。
  • dot(x, y): 计算点积。
  • cross(x, y): 计算叉积。

more: GLSL 内建函数 (opens new window)