This is a small practice to understand the new Webgpu API. I am not a Graphics Engineer, so probably a lot of mistakes were made but you are more than welcome to collaborate.
Download the repo and do npm i
and then npm start
to see this:
It was hugely inspired by how three.js works; you set a renderer, a scene, and a camera and you render them in a request animation frame, the only difference is that we need to request the WebGPU in advance and we will need to pass the camera to make it globally available:
import { Renderer } from "components/Renderer";
import { WGPU } from "components/WGPU";
import { PerspectiveCamera } from "components/Camera";
import { Scene } from "components/Scene";
import { Sphere } from "components/Geometry";
global.gpu = new WGPU();
const createApp = async () => {
await gpu.init();
const renderer = new Renderer();
const camera = new PerspectiveCamera(gpu.canvas.width / gpu.canvas.height);
camera.position.z = -3;
const scene = new Scene();
gpu.camera = camera;
const draw = () => {
renderer.render(camera, scene);
requestAnimationFrame(draw);
};
requestAnimationFrame(draw);
window.onresize = () => {
gpu.canvas.width = window.innerWidth;
gpu.canvas.height = window.innerHeight;
camera.aspect = gpu.canvas.width / gpu.canvas.height;
renderer.update();
};
};
createApp();
Now, we can import a geometry like a sphere and add it to the scene:
import { Renderer } from "components/Renderer";
import { WGPU } from "components/WGPU";
import { PerspectiveCamera } from "components/Camera";
import { Scene } from "components/Scene";
import { Sphere } from "components/Geometry";
global.gpu = new WGPU();
const createApp = async () => {
await gpu.init();
const renderer = new Renderer();
const camera = new PerspectiveCamera(gpu.canvas.width / gpu.canvas.height);
camera.position.z = -3;
const scene = new Scene();
gpu.camera = camera;
const sphere = new Sphere(1, 32, 32);
scene.add(sphere);
const draw = () => {
renderer.render(camera, scene);
requestAnimationFrame(draw);
};
requestAnimationFrame(draw);
window.onresize = () => {
gpu.canvas.width = window.innerWidth;
gpu.canvas.height = window.innerHeight;
camera.aspect = gpu.canvas.width / gpu.canvas.height;
renderer.update();
};
};
You can now make the sphere rotate like so:
import { Renderer } from "components/Renderer";
import { WGPU } from "components/WGPU";
import { PerspectiveCamera } from "components/Camera";
import { Scene } from "components/Scene";
import { Sphere } from "components/Geometry";
global.gpu = new WGPU();
const createApp = async () => {
await gpu.init();
const renderer = new Renderer();
const camera = new PerspectiveCamera(gpu.canvas.width / gpu.canvas.height);
camera.position.z = -3;
const scene = new Scene();
gpu.camera = camera;
const sphere = new Sphere(1, 32, 32);
scene.add(sphere);
const draw = () => {
sphere.rotation.x += 0.01;
renderer.render(camera, scene);
requestAnimationFrame(draw);
};
requestAnimationFrame(draw);
window.onresize = () => {
gpu.canvas.width = window.innerWidth;
gpu.canvas.height = window.innerHeight;
camera.aspect = gpu.canvas.width / gpu.canvas.height;
renderer.update();
};
};
If everything goes well, you should see this: