Skip to content

Latest commit

 

History

History
203 lines (152 loc) · 6.46 KB

File metadata and controls

203 lines (152 loc) · 6.46 KB

This page describes how to link Lygia shader functions into your WebGPU application using WESL tools.

WESL is a superset of WGSL that adds features with community-supported tools. WESL tools are available in Rust and JavaScript/TypeScript.

Most (but not all) Lygia GLSL shaders are now available for WebGPU using WESL. If a Lygia function you need is missing, please file an issue or help contribute.12

Using JavaScript or TypeScript

Install with npm install lygia or pnpm install lygia (lygia npm package). Once you install, 500+ Lygia functions and constants will be available for you to use via import statements in your application shader code.

import lygia::math::consts::PI;

fn main() {
  let p = PI;
}

The JS tools automatically tree-shake, including only the Lygia functions your application uses.

WESL integrates with popular bundlers (vite, webpack, rollup) through plugins, or for custom build pipelines, you can use the wesl-link command-line tool or the link API.

Using a JavaScript/TypeScript Bundler

If you build your application with a JavaScript/TypeScript bundler like vite, webpack or rollup, install the wesl and wesl-plugin packages.

Runtime Linking with a Bundler

Import shader code into your JavaScript or TypeScript application using the import statements suffixed with ?link and the shaders will be linked together at runtime:

import appWesl from "../shaders/app.wesl?link";
import { link } from "wesl";

const linked = await link(appWesl);
linked.createShaderModule(gpuDevice);

For more details, check the WESL bundler documentation or refer to this lygia example using vite.

Static Linking with a Bundler

Alternatively, you can statically link your shaders in advance using the ?static suffix:

import appWgsl from "../shaders/app.wesl?static";

See the lygia static linking example for details.

Runtime vs. Static Linking

Static linking bundles your shader modules together into a single transpiled WGSL string. Static linking means you don't need WESL linker in your runtime bundle (~15KB savings). However, static linking is less flexible because your application can't use WESL's conditional compilation features (@if directives) to adapt shaders at runtime based on GPU capabilities or user configuration.

Many Lygia shader functions include @if conditions. For example see @if(YUV_SDTV) in yuv2rgb. With runtime linking, you can set these conditions dynamically. With static linking, conditions are resolved at build time.

Command Line Linking

For custom build pipelines, use the wesl-link command-line tool to statically link shaders.

Linking Application Shaders

Link your application shader file that imports Lygia functions:

npx wesl-link ./shaders/main.wesl

See the Lygia CLI linking example for details.

Linking Lygia Modules on the Command Line

To get standalone WGSL for a specific Lygia module, call wesl-link on that module.

From the npm package:

npx wesl-link lygia::color::layer::addSourceOver

From a lygia repository clone:

npx wesl-link package::color::layer::addSourceOver

# alternate syntax
npx wesl-link color/layer/addSourceOver.wesl

Either approach produces the WGSL for the requested Lygia module linked with its dependencies.

Link Using the API

You can use the linking API directly to build custom solutions:

import { link } from "wesl";

const main = `import lygia::math::consts::PI; ...`;
const linked = await link({weslSrc: {main }});
const shaderModule = linked.createShaderModule(gpuDevice);

See the API documentation for details.

Additional WESL Examples

More WESL examples are available here. Most examples run with one click in a browser sandbox. The examples can also be used as starter templates with degit.

Using Rust

cargo add lygia

Linking at build time

cargo add --build wesl
/// build.rs
fn main() {
    wesl::Wesl::new("src/shaders").build_artifact("main.wesl", "my_shader");
}

Linking at run-time

cargo add wesl
let shader_string = Wesl::new("src/shaders")
    .compile("main.wesl")
    .inspect_err(|e| eprintln!("WESL error: {e}")) // pretty errors with `display()`
    .unwrap()
    .to_string();

Using the Rust CLI tool

cargo install wesl-cli
wesl compile <path/to/shader.wesl>

WESL Rust Documentation

See Getting Started Rust, the wesl crate documentation, and WESL rust examples.

About WESL

WESL extends WGSL with:

  • import statements to split shader code across files and load npm/cargo libraries
  • @if @else @elseif statements to assemble specialized shaders at build time or runtime

Current WESL tools include:

  • Linkers in Rust and JavaScript (to combine WGSL/WESL files into applications)
  • Syntax highlighters for zed, helix and nvim

Coming Soon

Additional WESL tools in development:

Read more about WESL at wesl-lang.dev.

Footnotes

  1. Lygia functions are small and self-contained. You can just copy, paste and edit them into your app if you prefer doing things manually!

  2. Lygia currently hosts two versions of WebGPU shaders. The newer versions use the WESL language and have a .wesl suffix. For new Lygia users, we recommend .wesl. (The older versions use a .wgsl suffix, but are less complete and use a custom #include syntax.)