Getting Started JavaScript - wgsl-tooling-wg/wesl-spec GitHub Wiki
Here's typical setup for a front end application using wesl and wesl-plugin/vite .
npm install wesl # for runtime linking
npm install --save-dev wesl-plugin # for bundler integration
/// vite.config.ts
import viteWesl from "wesl-plugin/vite";
import { linkBuildExtension } from "wesl-plugin";
export default {
plugins: [viteWesl({ extensions: [linkBuildExtension] })],
};
import { link, createWeslDevice } from "wesl";
import appWesl from "../shaders/app.wesl?link";
async function example() {
const device = createWeslDevice(await navigator.gpu.requestAdapter());
const linked = await link(appWesl);
const shaderModule = linked.createShaderModule(device, {});
}
WESL is easy to integrate into a diverse variety of JavaScript/TypeScript build environments. See JavaScript Builds .
./wesl.toml
- optional project configuration file
./shaders
- default location for .wesl and .wgsl files.
Customize configuration for your project by creating a wesl.toml
file
in the same directory as package.json
.
Here's an example:
/// wesl.toml
weslFiles = [ "./shaders/**/*.w[eg]sl" ]
weslRoot = "./shaders"
dependencies = ["random_wgsl"]
wesl.toml
settings below. All settings are optional.
A wesl.toml
is not required if the default setting are sufficient.
-
weslFiles - an array of globs locating shader files.
default
weslFiles = [ "./shaders/**/*.w[eg]sl" ]
-
weslRoot - ignored prefix for shader module paths.
import
statements inside wesl files use module paths (with::
separators). The module paths are mapped directly from shader file paths skipping past theweslRoot
.default
weslRoot = [ "./shaders" ]
-
dependencies - list of npm package names for shader dependencies
All dependencies should also be listed in
package.json
. Only direct dependencies should be listed.default -
dependencies = []
wesl.toml
is used by development tools like the wesl-plugin, wesl-packager,
and the forthcoming WESL language server.
The link()
API enables runtime control of WESL shader transpilation.
Runtime linking options allow for adapting shaders to user application environments:
- Tune shaders based on runtime checks of GPU capabilities
- Customize shaders according on web application settings
- Augment shaders with frameworks that dynamically generate shader fragments,
- Extend the linker itself with wesl-js extensions
To set a condition for use in @if
conditional translation,
pass a conditions
option to link()
with boolean values for the conditions.
Unset conditions are presumed falsy.
/// main.ts
import appWesl from "../shaders/app.wesl?link";
link({...appWesl, conditions: { MOBILE: true }});
/// app.wesl
@if(MOBILE) var size = 8;
To inject constants from JavaScript/TypeScript for WESL shader compilation,
pass a constants
option to link()
with string or numeric values for the constants.
WESL shaders can use the constants by importing from the constants
virtual module.
/// main.ts
link({..., constants: { NumLights: 7 }});
/// app.wesl
var<private> lights: array<vec3f, constants::NumLights>;
To use a function that generates WESL/WGSL shader code from JavaScript at runtime,
use the virtualLibs
option.
Pass a record with the name of the virtual module as a key,
and the generating function as a value.
/// main.ts
link({..., virtualLibs: { MyCustom: () => "fn custom() {}" }});
/// app.wesl
import MyCustom::custom;
fn example() {
custom();
}
To plug in a custom extension that extends the linker itself with a WeslJsPlugin,
use the config
option.
/// main.ts
link({..., config: { plugins: bindingStructsPlugin() }});
See LinkParams for further details on runtime linking options.