Three.js Teapot
The Utah teapot rendered by Three.js, with an Adwaita sidebar that changes the geometry and the material while it spins.
Three.js runs unmodified: THREE.WebGLRenderer, TeapotGeometry and OrbitControls come straight from npm and draw into a Gtk.GLArea. The controls beside it are real GTK widgets bound to the scene, so you can wrap a web renderer in a native GNOME interface instead of rebuilding one in HTML.
Ported from the upstream webgl_geometry_teapot example.
Live demo
Section titled “Live demo”Run it
Section titled “Run it”It declares all four runtimes, so pick the one you have:
gjsify showcase three-geometry-teapot --runtime gjsgjsify showcase three-geometry-teapot --runtime nodegjsify showcase three-geometry-teapot --runtime bungjsify showcase three-geometry-teapot --runtime denoA GTK 4 window opens as an Adw.OverlaySplitView. The sidebar holds the controls, the canvas fills the rest. Drag to orbit the camera, scroll to zoom. Same window and same scene on all four.
The sidebar has two groups. Geometry sets the tessellation level (an Adw.ComboRow stepping 2, 3, 4, 5, 6, 8, 10, 15, 20, 30, 40, 50) and toggles Display Lid, Display Body, Display Bottom, Snug Lid and Original Scale. Material switches the shading between wireframe, flat, smooth, glossy, textured and reflective.
--runtime gjs runs the --app gjs bundle against GJS’s native gi://. The other three share one --app node bundle, where gi:// goes through the node-gi bridge. Leave the flag off and Choose the runtime says what the CLI picks.
Run it in the browser
Section titled “Run it in the browser”import { mount } from '@gjsify/example-dom-three-geometry-teapot/browser';
const handle = mount(document.getElementById('app')!, { assetBase: '/demos/teapot/', // where the UV grid and the Pisa cubemap live});
handle.pause();handle.resume();The browser build rebuilds the same sidebar out of @gjsify/adwaita-web custom elements, so both versions look and behave the same.
What it uses
Section titled “What it uses”| Package | What Three.js needs it for |
|---|---|
@gjsify/webgl | The whole WebGL 2.0 API: vertex array objects, uniform buffer objects, texStorage2D, drawElementsInstanced |
@gjsify/dom-elements | HTMLCanvasElement and requestAnimationFrame |
@gjsify/event-bridge | Mouse drag and scroll feeding OrbitControls |
@gjsify/adwaita-web | The sidebar in the browser build |
| Libadwaita | Adw.OverlaySplitView, Adw.ComboRow and Adw.SwitchRow in the GTK build |
@gjsify/webgl maps WebGL calls onto the platform’s own GL through a Vala bridge, which is GLES 3.2 on Linux. Three.js targets desktop WebGL, does not know about that difference, and does not have to. Bridge widgets has the detail.
Copy the structure
Section titled “Copy the structure”showcases/dom/three-geometry-teapot/
src/three-demo.tsis the whole scene behind onestart(canvas)function, with no platform imports. It also exportsTESS_VALUESandSHADING_VALUESso both shells build the same control lists.src/gjs/gjs.ts,teapot-window.tsandteapot-window.blpare theAdw.Application, the window class and its Blueprint UI.src/browser/browser.tsexportsmount();browser-main.tsruns it full-page.src/assets/carries the UV grid texture and the Pisa cubemap, published through the package’s./assets/*export.
Exporting your control values from the shared module, as TESS_VALUES does here, is the cheap way to stop two shells drifting apart.
Related
Section titled “Related”three-postprocessing-pixelruns the same engine through a multi-pass post-processing chain.three-loader-ldrawloads its geometry from disk overfetch.- Bridge widgets covers the
WebGLBridgelifecycle and the resize path.