WGSL需要明确直到每个变量、结构字段、函数参数和函数返回值的类型。
普通类型
- i32 :32位有符号整型
- u32 :32位无符号整型
- f32 :32位浮点型
- bool :boolean类型
- f16 :16位浮点型 (可选功能,需要主动开启)
变量声明
在WGSL中,所有变量都具有块作用域。var是一个具有存储空间的变量,因此是可变的。let为常数值,不可变。const不是一个变量,它是一个编译时常数。运行时发生变化的对象不能使用const。
const one: f32 = 1;
var a: f32 = 1;
let c: f32 = 3;
fn d(e: f32) -> f32 { return e * 2; }
矢量Vector
WGSL中有3种矢量类型vec2、vec3和vec4。他们的基本风格是vec?,所以vec2是一个包含2个i32数值的矢量,vec3是一个包含3个f32元素的矢量,vec4是一个包含4个u32数值的矢量,vec3一个包含3个布尔值的矢量。
let a = vec2<i32>(1, -2);
let b = vec3<f32>(3.4, 5.6, 7.8);
let c = vec4<u32>(9, 10);
//如何访问
let a = vec4<f32>(1, 2, 3, 4);
let b = a.z; // via x,y,z,w
let c = a.b; // via r,g,b,a
let d = a[2]; // via array element accessors
//一次访问多个元素
let a = vec4<f32>(1, 2, 3, 4);
let b = a.zx; // via x,y,z,w
let c = a.br; // via r,g,b,a
let d = vec2<f32>(a[2], a[0]);
数学运算
let a = vec4f(1, 2, 3, 4);
let b = vec4f(5, 6, 7, 8);
let c = a + b; // c is vec4f(6, 8, 10, 12)
let d = a * b; // d is vec4f(5, 12, 21, 32)
let e = a - b; // e is vec4f(-4, -4, -4, -4)
//函数
let a = vec4f(1, 2, 3, 4);
let b = vec4f(5, 6, 7, 8);
let c = mix(a, b, 0.5); // c is vec4f(3, 4, 5, 6)
let d = mix(a, b, vec4f(0, 0.5, 0.5, 1)); // d is vec4f(1, 4, 5, 8)
矩阵Matrices
WGSL中包含很多矩阵类型,矩阵可以看作是一组矢量。格式为matx<>,以mat3x4为例,可以看作是3个vec4。和矢量一样,矩阵也有简写形式
// a 和 b 类型一样
let a: mat4x4<f32> = ...
let b: mat4x4f = ...
// 访问
let a = mat4x4f(...);
let b = a[2]; // b is a vec4f of the 3rd vector of a
数组arrays
WGSL中数组可以通过array<type, numElements>进行声明。
let a = array<f32, 5>; // an array of five f32s
let b = array<vec4f, 6>; // an array of six vec4fs
// 其它构造方式,它接受任意数量的参数并返回一个数组,而且参数必须是相同的类型。
let arrOf3Vec3fsA = array(vec3f(1,2,3), vec3f(4,5,6), vec3f(7,8,9));
let arrOf3Vec3fsB = array<vec3f, 3>(vec3f(1,2,3), vec3f(4,5,6), vec3f(7,8,9));
// runtime sized arrays
@group(0) @binding(0) var<storage> foo: array<mat4x4f>;
// 使用arrayLength查询长度。
let numMatrices = arrayLength(&foo);
函数functions
WGSL中函数声明形式为fn name(parameters) -> returnType { ..body... }
fn add(a: f32, b: f32) -> f32 {
return a + b;
}
着色器入口entry points
WGSL代码需要一个入口函数,可以通过@vertex, @fragment 或 @compute进行标识。
@vertex fn myFunc(a: f32, b: f32) -> @builtin(position): vec4f {
return vec4f(0, 0, 0, 0);
}
属性attributes
单词attributes在WebGPU中有两种含义,一种是顶点属性(vertex attributes)在顶点缓存区已经介绍过。另一种是WGSL中以@开头的属性。
@location(number) //用来定义着色器的输入和输出。
阶段变量inter stage variables
对于阶段变量,@location属性定义变量在着色器之间传递的位置。
struct VSOut {
@builtin(position) pos: vec4f,
@location(0) color: vec4f,
@location(1) texcoords: vec2f,
};
struct FSIn {
@location(1) uv: vec2f,
@location(0) diffuse: vec4f,
};
@vertex fn foo(...) -> VSOut { ... }
@fragment fn bar(moo: FSIn) ...
片元着色器输出fragment shader outputs
在片元着色器中@location指定了使用哪个GPURenderPassDescriptor.colorAttachment存储结果。
struct FSOut {
@location(0) albedo: vec4f;
@location(1) normal: vec4f;
}
@fragment fn bar(...) -> FSOut { ... }
// @builtin(name)属性通常用于指定来之WebGPU内置变量的值。
@vertex fn vs1(@builtin(vertex_index) foo: u32, @builtin(instance_index) bar: u32) ... {
...
}
流程控制 flow control
// for ////////////////
for (var i = 0; i < 10; i++) { ... }
// if //////////////////
if (i < 5) {
...
} else if (i > 7) {
..
} else {
...
}
// while ///////////////////
var j = 0;
while (j < 5) {
...
j++;
}
// loop //////////////////////////
var k = 0;
loop {
k++;
if (k >= 5) {
break;
}
}
// break
var k = 0;
loop {
k++;
if (k >= 5) {
break;
}
}
// break if
var k = 0;
loop {
k++;
break if (k >= 5);
}
// continue
for (var i = 0; i < 10; ++i) {
if (i % 2 == 1) {
continue;
}
...
}
// continuing
for (var i = 0; i < 10; ++i) {
if (i % 2 == 1) {
continue;
}
...
continuing {
// continue goes here
...
}
}
// discard
if (v < 0.5) {
discard;
}
// discard仅在片元着色器中可以使用。
// switch /////////////////////////
var a : i32;
let x : i32 = generateValue();
switch x {
case 0: { // The colon is optional
a = 1;
}
default { // The default need not appear last
a = 2;
}
case 1, 2, { // Multiple selector values can be used
a = 3;
}
case 3, { // The trailing comma is optional
a = 4;
}
case 4 {
a = 5;
}
}