WebGPU 着色器语言 WGSL 介绍及与 GLSL 的对比

本文介绍了WebGPU中的新着色语言WGSL,旨在为从OpenGL/GLSL迁移到WebGPU的开发者提供帮助。WGSL是对现代着色器语言的重新设计,与GLSL在入口点、工作组、纹理处理等方面有显著差异。文章通过对比GLSL,详细讲解了WGSL的结构体、函数语法、纹理操作等关键特性,强调了WGSL的清晰性和灵活性。
摘要由CSDN通过智能技术生成

WGSL 的来由

WebGPU 的目标是要在各个现代底层图形 API 之上抽象出一套统一的图形 API,而每个底层图形 API 后端都有自己的着色语言:

  • DirectX 使用 HLSL(High Level Shading Language)
  • Metal 使用 MSL(Metal Shading Language)
  • OpenGL使用 GLSL(OpenGL Shading Language)
  • Vulkan 使用的着色语言又跟之前的图形 API 都不同,它的着色器必须以 SPIR-V 这种二进制字节码的格式提供(有一些库能提供将其它语言编写的着色器编译为 SPIR-V 的能力,比如 shaderc )。

WGSL 出现之前,很多开发者或团队是通过宏及各种转译工具来将自己的着色器编译到不同目标平台的,他们自然是希望有一个标准化的统一语言。

WebGPU 成员花了 2 年半的时间来争论 WebGPU 是否应该有自己的着色语言。kvark 将这场争论中的核心论点组成了一张流图,它是 SVG 格式的,支持在网页中无损放大查看。

WGSL 的目标不是要与 GLSL 兼容,它是对现代着色器语言的全新重新设计。

2020 年 4 月 27 日,WGSL 标准有了第一次提交。自此开始,wgpu 和 dawn 都摆脱了对 shaderc 之类复杂繁重的着色器转译工具的依赖。wgpu 里使用的 WGSL 转译工具叫 naga, kvark 有一篇博客(Shader translation benchmark)对比了 naga 相比于其它转译工具的性能优化,总体来说,有 10 倍以上的性能优势。

目前学习 WGSL 的资源着实很少 —— 唯一好的参考是 WGSL 规范,但它是对语言实现细节的规范,对普通用户来说有点难以理解。我从 2018 年开始使用 wgpu (那时还是 使用 GLSL 做为着色器语言),2021 年底完成了个人作品 字习 Pro 及其他几个练手作品从 GLSL 到 WGSL 的 100 多个着色器的移植工作,在这个过程中对这两个着色器语言有了比较深入的了解。这个增补章节旨在介绍 WGSL 的一些基础知识,希望这对从 OpenGL / WebGL 迁移到 WebGPU 的朋友带来一点有益的经验(下边的所有 GLSL 代码均是按照 GLSL450 标准编写的)。

一个简单的绘制着色器:对比 GLSL

GLSL 的绘制着色器:

// 顶点着色器文件
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
layout(location = 0) out vec2 uv;

layout(set = 0, binding = 0) uniform UniformParams {
   
    mat4 mvp_matrix;
    vec3 tint_color;
};

void main() {
   
    gl_Position = mvp_matrix * vec4(position, 1.0);
    uv = texcoord;
}

// 片元着色器文件
layout(location = 0) in vec2 uv;
layout(location = 0) out vec4 frag_color;

layout(set = 0, binding = 0) uniform UniformParams {
   
    mat4 mvp_matrix;
    vec3 tint_color;
};
layout(set = 0, binding = 1) uniform texture2D textureFront;
layout(set = 0, binding = 2) uniform sampler samplerFront;

void main(void) {
   
  vec4 front = texture(sampler2D(textureFront, samplerFront), uv);
  frag_color = front * vec4(tint_color.rgb, 1.0);;
}

下边是使用 WGSL 的等价实现,在 WGSL 中,我们通常将顶点着色器与片元着色器写在同一个文件中:

struct VertexOutput {
   
    @location(0) uv: vec2<f32>,
    @builtin(position) position: vec4<f32>,
};

struct UniformParams {
   
    mvp: mat4x4<f32>,
	tint_color: vec3<f32>,
};

@group(0) @binding(0) var<uniform> params: UniformParams;

@vertex
fn vs_main(@location(0) pos: vec3<f32>, @location(1) uv: vec2<f32>) -> VertexOutput {
   
    var out: VertexOutput;
    out.position = params.mvp * vec4<f32>(pos, 1.0);
    out.uv = uv;
    return out;
}

@group(0) @binding(1) var texture_front: texture_2d<f32>;
@group(0) @binding(2) var sampler_front: sampler;

@fragment
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
   
    let front = textureSample(texture_front, sampler_front, input.uv);
    return front * vec4<f32>(params.tintColor, 1.0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李金磊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值