{"id":17149615,"url":"https://github.com/martinlaxenaire/gpu-curtains","last_synced_at":"2026-04-01T18:38:33.476Z","repository":{"id":218540495,"uuid":"645702364","full_name":"martinlaxenaire/gpu-curtains","owner":"martinlaxenaire","description":"gpu-curtains is a 3D WebGPU rendering engine. It can be used as a standalone 3D engine, but also includes extra classes focused on mapping 3d objects to DOM elements; It allows users to synchronize values such as position, sizing, or scale between them.","archived":false,"fork":false,"pushed_at":"2025-03-25T12:50:04.000Z","size":226912,"stargazers_count":121,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-27T05:07:11.230Z","etag":null,"topics":["3d","canvas","curtains","curtainsjs","dom","html5","javascript","webgpu"],"latest_commit_sha":null,"homepage":"https://martinlaxenaire.github.io/gpu-curtains/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/martinlaxenaire.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["martinlaxenaire"]}},"created_at":"2023-05-26T08:42:59.000Z","updated_at":"2025-03-25T16:13:18.000Z","dependencies_parsed_at":"2024-02-08T09:27:37.390Z","dependency_job_id":"1c3e522f-c4e2-4adf-81b0-ef1d883803f4","html_url":"https://github.com/martinlaxenaire/gpu-curtains","commit_stats":null,"previous_names":["martinlaxenaire/gpu-curtains"],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinlaxenaire%2Fgpu-curtains","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinlaxenaire%2Fgpu-curtains/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinlaxenaire%2Fgpu-curtains/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinlaxenaire%2Fgpu-curtains/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/martinlaxenaire","download_url":"https://codeload.github.com/martinlaxenaire/gpu-curtains/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247234920,"owners_count":20905854,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d","canvas","curtains","curtainsjs","dom","html5","javascript","webgpu"],"created_at":"2024-10-14T21:33:34.879Z","updated_at":"2026-04-01T18:38:33.466Z","avatar_url":"https://github.com/martinlaxenaire.png","language":"TypeScript","funding_links":["https://github.com/sponsors/martinlaxenaire"],"categories":["TypeScript"],"sub_categories":[],"readme":"# gpu-curtains\n\n\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/martinlaxenaire/gpu-curtains/main/website/assets/gpu-curtains-logo-1080-720.jpg\" width=\"500\" alt=\"gpu-curtains\" /\u003e\n\u003c/div\u003e\n\n[Website](https://martinlaxenaire.github.io/gpu-curtains/) - [Documentation](https://martinlaxenaire.github.io/gpu-curtains/docs/) - [Examples](https://martinlaxenaire.github.io/gpu-curtains/examples/)\n\n---\n\n\u003e :warning: WIP\n\n---\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://npmjs.org/package/gpu-curtains\"\u003e\n        \u003cimg src=\"https://img.shields.io/npm/v/gpu-curtains\" alt=\"version\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://bundlephobia.com/result?p=gpu-curtains\"\u003e\n        \u003cimg src=\"https://img.shields.io/bundlephobia/minzip/gpu-curtains\" alt=\"size\" /\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n### DOM 2 WebGPU rendering engine\n\ngpu-curtains is a small, lightweight 3D WebGPU rendering engine library.\n\nIt can be used as a standalone 3D engine, but also includes extra classes designed to turn HTML elements into textured planes or meshes, allowing you to animate them via WGSL shaders.\n\nThe project was initially conceived as a WebGPU port of [curtains.js](https://github.com/martinlaxenaire/curtainsjs). It turned out to be a complete rewrite of the library instead, but with a very similar API.\n\n## Usage\n\nYou can directly download the files and start using the ES6 modules:\n\n#### ES modules\n\n```javascript\nimport { GPUCurtains } from 'path/to/dist/esm/index.mjs'\n\nwindow.addEventListener('load', async () =\u003e {\n  // set our main GPUCurtains instance\n  // it will handle everything we need\n  // a WebGPU device and a renderer with its scene,\n  // requestAnimationFrame, resize and scroll events...\n  const gpuCurtains = new GPUCurtains({\n    container: '#canvas',\n  })\n\n  // set the GPU device\n  // note this is asynchronous\n  await gpuCurtains.setDevice()\n\n  // now create some magic!\n})\n```\n\nYou can also use one of your favorite package manager:\n\n#### npm\n\n```\nnpm i gpu-curtains\n```\n\n#### yarn\n\n```\nyarn add gpu-curtains\n```\n\nFinally, you can load the library from a CDN. You should always target a specific version (append `@x.x.x`) rather than the latest one in order to avoid breaking changes.\n\n```javascript\nimport { ... } from 'https://esm.run/gpu-curtains'\n// or\nimport { ... } from 'https://cdn.skypack.dev/gpu-curtains'\n// or use another cdn...\n```\n\n#### UMD files\n\nIn a browser, you can use the UMD files located in the `dist` directory:\n\n```html\n\u003cscript src=\"path/to/dist/gpu-curtains.umd.min.js\"\u003e\u003c/script\u003e\n```\n\nOr use a CDN:\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/gpu-curtains\"\u003e\u003c/script\u003e\n```\n\n## Documentation and examples\n\n- [API documentation](https://martinlaxenaire.github.io/gpu-curtains/docs/)\n- [Official examples](https://martinlaxenaire.github.io/gpu-curtains/examples/)\n- [Website](https://martinlaxenaire.github.io/gpu-curtains/)\n\n## Basic example\n\n### HTML\n\n```html\n\u003cbody\u003e\n  \u003c!-- div that will hold our WebGPU canvas --\u003e\n  \u003cdiv id=\"canvas\"\u003e\u003c/div\u003e\n\u003c/body\u003e\n```\n\n### CSS\n\n```css\nbody {\n  position: relative;\n  width: 100%;\n  height: 100%;\n  margin: 0;\n  overflow: hidden;\n}\n\n#canvas {\n  /* make the canvas wrapper fits the viewport */\n  position: fixed;\n  top: 0;\n  right: 0;\n  width: 100%;\n  height: 100lvh;\n}\n```\n\n### Javascript\n\n```javascript\nimport { GPUDeviceManager, GPUCameraRenderer, Mesh } from 'gpu-curtains'\n\nwindow.addEventListener('load', async () =\u003e {\n  // first, we need a WebGPU device, that's what GPUDeviceManager is for\n  const gpuDeviceManager = new GPUDeviceManager({\n    label: 'Custom device manager',\n  })\n\n  // we need to wait for the device to be created\n  // note this is asynchronous\n  await gpuDeviceManager.init()\n\n  // create a camera renderer\n  const gpuCameraRenderer = new GPUCameraRenderer({\n    deviceManager: gpuDeviceManager,\n    container: document.querySelector('#canvas'),\n  })\n\n  // create a cube mesh\n  const mesh = new Mesh(gpuCameraRenderer, {\n    geometry: new BoxGeometry(),\n  })\n\n  // this callback is executed\n  // before the scene actually updates the matrix stack\n  mesh.onBeforeRender(() =\u003e {\n    // make it rotate\n    mesh.rotation.x += 0.01\n    mesh.rotation.y += 0.02\n  })\n})\n```\n\n## Limitations\n\ngpu-curtains is a slowly evolving 3D engine and still is a work in progress.\n\nIt can now handle built-in lights (`AmbientLight`, `DirectionalLight`, `PointLight` and `SpotLight`) with shadows, `EnvironmentMap` and standard mesh lighting materials out of the box (such as `Lambert`, `Phong` and `PBR`).\n\nglTF support is also coming along nicely. All the core features are supported, and a bunch of extensions are also available.\n\nIf you need a more robust 3D engine that could handle all the glTF extensions, advanced lighting setup (such as light probes), shading or rendering mechanics, then you should probably go with another library like [three.js](https://github.com/mrdoob/three.js) or [Babylon.js](https://github.com/BabylonJS).\n\n## Debugging\n\nIf you need to debug your scenes, understand in which order they are rendered or inspect your textures, I strongly recommend you to have a look at [Brendan Duncan's WebGPU inspector extension](https://github.com/brendan-duncan/webgpu_inspector).\n\n## Contributing\n\nContribution are more than welcome! Please refer to the [contribution guidelines](CONTRIBUTING.md).\n\n## Resources\n\nI've wrote a 4 parts tutorial on [OKAY DEV](https://okaydev.co/). Altho it uses a deprecated version of the library, it is still pretty useful to understand the library basics and how things are built under the hood.\n\n- [Dive Into WebGPU — Part 1 (basic scene)](https://okaydev.co/articles/dive-into-webgpu-part-1)\n- [Dive Into WebGPU — Part 2 (DOM synced gallery with post-processing)](https://okaydev.co/articles/dive-into-webgpu-part-2)\n- [Dive Into WebGPU — Part 3 (glTF product configurator)](https://okaydev.co/articles/dive-into-webgpu-part-3)\n- [Dive Into WebGPU — Part 4 (instanced particles with shadow map)](https://okaydev.co/articles/dive-into-webgpu-part-4)\n\n## Acknowledgements\n\nSome parts of the code (mostly the math classes) have been ported or adapted from other existing open source libraries like [three.js](https://github.com/mrdoob/three.js) and [glmatrix](https://github.com/toji/gl-matrix).\n\nSome examples are also ported and/or inspired by other online open-source WebGL or WebGPU examples. In any case the source should always be credited in the code. If a credit is missing, feel free to reach out or make a PR.\n\nThe [WebGPU samples](https://github.com/webgpu/webgpu-samples), [WebGPU fundamentals](https://webgpufundamentals.org/) and [WebGPU best practices](https://toji.dev/webgpu-best-practices/) were very helpful to help with the basic concepts of WebGPU. If you want to understand a bit more how it's working under the hood, do not hesitate to check those.\n\nA big thanks to the members of the [WebGPU matrix chan](https://matrix.to/#/#WebGPU:matrix.org) that were always super kinds and very helpful as well.\n\n## Changelog and roadmap\n\n- [Releases](https://github.com/martinlaxenaire/gpu-curtains/releases)\n- See the [roadmap](ROADMAP.md) for details on the current work in progress and possible improvements.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinlaxenaire%2Fgpu-curtains","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartinlaxenaire%2Fgpu-curtains","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinlaxenaire%2Fgpu-curtains/lists"}