-
Notifications
You must be signed in to change notification settings - Fork 1
Getting Started
WESL is designed to work with both JavaScript and Rust. We have two distinct implementations for these languages, wesl-js and wesl-rs.
Wesl can be operated in a few different ways:
- Using the standalone Command-Line tool to generate WGSL files.
- At build-time, using a Vite Plugin (JavaScript) or a Build Script (Rust).
- At run-time, using the linker libraries.
(TODO)
wesl-rs documentation: (TODO link)
- Install the CLI:
cargo install --git https://github.com/wgsl-tooling-wg/wesl-rs wesl-cli - Compile a shader:
wesl compile <path/to/shader.wesl> - Type
wesl --helpor visit the crate documentation (coming soon) for more configuration options.
- Add wesl-rs to your build-dependencies:
cargo add --git https://github.com/wgsl-tooling-wg/wesl-rs --build wesl - Create the file
build.rsright next to yourCargo.toml. - Paste this content:
fn main() { wesl::Wesl::new_spec_compliant("src/shaders").build_artefact("main.wesl", "my_shader"); }
- Place your shader in
src/shaders/main.wesl. - Paste this code where you want to access your shader string in Rust code:
use wesl::include_wesl; const shader_string = include_wesl!("my_shader");
- Add wesl-rs to your dependencies:
cargo add --git https://github.com/wgsl-tooling-wg/wesl-rs wesl - Place your shader in
src/shaders/main.wesl. - Paste this code where you want to access your shader string in Rust code:
let shader_string = Wesl::new_spec_compliant("src/shaders") .compile("main.wesl") .inspect_err(|e| eprintln!("WESL error: {e}")) // pretty errors with `display()` .unwrap() .to_string();
WESL currently provides these functionalities:
- Imports allow splitting code in multiple files.
- Packages are collections of general-purpose shader modules published to npm (JavaScript) and crates.io (Rust).
-
Conditional Translation is a mechanism to conditionally include/exclude chunks of code. Similar to
#ifdef(C/C++) or#[cfg](Rust). - ...More Coming Soon!
Import statements are placed at the top of your file. All they do is add a declaration present in another file to the scope.
import sdf::primitives::box; // import function `box` in module `primitives` in package `sdf`.
import package::bindings::mySampler; // import declaration `mySampler` from file `bindings.wesl` located at the root of this package.
import super::util; // import the entire sibling module `./util.wesl`.
import package::animals::{ // you can nest imports with `{ }`.
bird,
mammals::{ dog, cat }
};- What can be imported? - You can import all top-level declarations in a file: functions, structs, variables and aliases. You can also import whole modules.
-
How to locate a file? - The first segment indicate where to look for the file:
- If it is
super, start from the folder containing the current file. You can chainsupers to walk up the file tree. - If it is
package, start at the package root (provided to the linker). - Any other name corresponds to an external package.
- If it is
In addition to import statements, you can write directly the path to a declaration at the usage site.
import package::math;
fn main() {
package::my_mod::my_submod::my_fn(); // import statement not required.
let x = math::constants::PI; // module `math` was imported, you can access its declarations with a qualified name.
}The @if(condition) attribute makes the following element optionally included in the final shader, depending on the condition.
The condition is made of feature flags which are set when you invoke the linker (wesl-js or [wesl-rs]).
@if(debug_mode && !raytracing_disabled) // attributes on top-level declarations
var<private> debug_count_iterations: i32 = 0;
@if(is_2d)
alias point = vec2f;
@if(!is_2d) // the @else block is in discussion, meanwhile just negate the if condition.
alias point = vec3f;
struct Line {
start_point: point, end_point: point,
@if(colored) color: vec4f,
}
fn fibonacci(n: u32) {
@if(use_lookup_table) { // attributes on blocks `{ }`
const lut = array(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144);
return lut[n];
}
// ...
}The condition is a boolean expression containing: feature names, && (and), || (or), ! (not), true and false.
You can place attributes on declarations (functions, structs, variables, etc.), statements, struct members and function parameters.
Visit the Reference page for the complete documentation of WESL Extensions.