npm i --save-exact @wgsl-canvas/core
If you're using TypeScript, it would be helpful to add @webgpu/types, so your codebase will be aware of WebGPU-related types.
npm i --save-dev @webgpu/types
Then add them into your tsconfig.json
.
{
// ...
"compilerOptions": {
// ...
"types": ["@webgpu/types"]
}
}
Here's the base example for you to get started.
import { WGSLCanvas } from "@wgsl-canvas/core";
// 1. Check WebGPU support
if (!WGSLCanvas.isSupported()) {
alert("WebGPU is not supported in this browser");
return;
}
// 2. Create a canvas
const canvas = document.createElement("canvas");
canvas.width = 500;
canvas.height = 500;
document.body.appendChild(canvas);
// 3. Create an instance of "WGSLCanvas" and initialize it
const wgslCanvas = new WGSLCanvas({ canvas });
await wgslCanvas.init();
// 4. Make your first render
wgslCanvas.render();
If everything is set up correctly, you should see this output (which is the default fragment shader located under WGSLCanvas.SHADER_FRAGMENT_DEFAULT
static field).
See full example here.
To pass your shader, define it as a string of WGSL code.
const shaderFragment = /* wgsl */`
struct FragmentOutput {
@location(0) color: vec4<f32>,
}
@fragment
fn fragment_main() -> FragmentOutput {
var output: FragmentOutput;
output.color = vec4<f32>(0.1, 0.2, 0.25, 1.0);
return output;
}
`;
Then pass it to WGSLCanvas
instance via shaderFragment
property.
wgslCanvas.shaderFragment = shaderFragment;
If you want to store your WGSL code under .wgsl
files, you should configure your bundler to be able to resolve them as strings. The easiest way is to start with Vite, which can do this out of the box using ?raw
suffix.
See full example here.
To pass uniforms to your shader, you should first define them in uniformsKeys
array in your WGSLCanvas
instance.
wgslCanvas.uniformsKeys = ["time", "color1", "color2"];
Then, you can pass the values into uniforms
object.
wgslCanvas.uniforms.time = 0.0;
wgslCanvas.uniforms.color1 = [1.0, 0.0, 0.0];
wgslCanvas.uniforms.color2 = [0.0, 0.0, 1.0];
Then, they'll be available under var<uniform>
object at @group(0), @binding(0)
in your WGSL shader.
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
struct Uniforms {
time: f32,
color1: vec3<f32>,
color2: vec3<f32>,
}
The order of keys in struct Uniforms
must be the same as defined in uniformsKeys
array!
See full example here.
Make sure you have your texture file served under some URL (can be absolute or relative).
Then, you can load it via WGSLCanvas.loadTexture
static method to get an ImageBitmap
image.
const textureUrl = "https://example.com/YOUR_TEXTURE.jpg";
const texture = await WGSLCanvas.loadTexture(textureUrl);
Then, pass it into the textures
array of your WgslCanvas
instance.
wgslCanvas.textures = [texture];
In WGSL shader, it'll appear under the following vars.
@group(0) @binding(0) var texture_sampler: sampler;
@group(0) @binding(1) var texture: texture_2d<f32>;
If you have uniforms, they will appear at @binding(0)
, but sampler
and textures
will appear under their bindings incremented by 1.
See full example here.
Check out various examples here.