Models and shaders
Publish a real glTF model with orbit controls, a static poster, and an original-file download.
On this page
AlkModel displays an uncompressed glTF 2.0 .glb or .gltf file with Three.js. Alkemist provides the figure shell, lazy loading, camera controls, theming, fallback, and cleanup. The file itself stays downloadable.
Add a model
Place the model and any associated textures in your site’s public directory. A self-contained GLB is convenient for publishing; a .gltf document can reference separate binary and texture files, whose relative URLs must remain valid.
import AlkModel from '@alkemist/ui/AlkModel.astro';
<AlkModel
src="/test/torus-knot.glb"
poster="/test/torus-knot.svg"
title="A (2, 3) torus knot"
description="A deterministic tube mesh around a closed torus-knot curve."
/>3D model · glTF 2.0
A (2, 3) torus knot
This owned teaching fixture contains 4,825 vertices and 9,216 triangles. Its geometry is generated reproducibly; it is not a scan or a manufactured part.
The component uses the project’s pinned Three.js GLTFLoader. It does not currently configure Draco, Meshopt, or KTX2 decoders, so models depending on those compression extensions need an uncompressed export.
Props
The public prop type is AlkModelProps.
| Prop | Required | Meaning |
|---|---|---|
src | Yes | Model URL |
title | Yes | Visible figure title and accessible control label |
description | No | Context, provenance, units, or an explanation of the geometry |
poster | No | Static image shown while loading and when the interactive renderer is unavailable |
class | No | Additional class on the figure’s custom element |
Include a meaningful poster and description for published research. A poster is optional in the API, but it gives readers useful content before the GPU viewer starts and if their browser cannot render the scene.
Interaction
- Drag to orbit and scroll to zoom.
- Use Front, Top, and Reset view to return to known camera positions.
- Focus the canvas and use the arrow keys to orbit,
+/−to zoom, and Home to reset. - Toggle Wireframe to inspect mesh structure.
- Enable Spin explicitly for continuous rotation; it starts off, pauses offscreen, and stops when the reduced-motion preference changes to reduce.
Orbit navigation uses Three.js OrbitControls. The canvas and controls expose keyboard labels, but a 3D canvas is not a complete nonvisual representation of complex geometry. The title, description, poster, and original file are part of the figure’s accessible content.
Theme and lifecycle
The board color determines the scene background. Ordinary model materials retain their authored colors. Alkemist’s own teaching fixture opts into the shared cobalt ink with material metadata extras: { alkInk: "cobalt" }, so that material uses the same #1982f2 on whiteboard and blackboard.
The engine imports when the viewer approaches the viewport. Idle and offscreen scenes do not run a continuous animation loop. Rendering caps device pixel ratio at 2; removed viewers release geometry, materials, textures, renderer resources, and decoded image bitmaps. These explicit disposals follow Three.js resource cleanup guidance.
A network or WebGL failure leaves the static poster, explanatory state, and original download available. It does not replace the requested model with an unrelated synthetic object.
The specimen and current limits
The torus-knot fixture is generated by scripts/generate-test-model.mjs. Its poster and GLB belong to this repository and can be regenerated. The test page exercises the viewer alongside other media.
This version has no animation timeline, skeletal animation controls, measurement tools, physical unit conversion, mesh editing, or model generation. NeRF exports, Gaussian splats, point clouds, STL/OBJ adapters, and robotics/URDF viewers remain separate future capabilities. A shared figure design does not make their file formats interchangeable.
A live shader study
AlkShader is a reusable, bounded two-source interference specimen. It evaluates a dimensionless field in GLSL, with frequency and source-angle controls. The eight categorical inks distinguish contour bands; a static SVG remains visible until the GPU renderer is ready.
import AlkShader from '@alkemist/ui/AlkShader.astro';
<AlkShader title="Interference field" frequency={9} angle={24} />Its public prop type is AlkShaderProps. title defaults to “Interference field,” frequency defaults to 9 and is clamped to 3–18, and angle defaults to 24 degrees and is clamped to 0–180. class adds a custom class. Native range controls let readers change those values; Play waves explicitly starts motion.
The implementation uses WebGL2 and GLSL ES 3.00. While paused, changing a control renders one frame. Playing advances phase at 0.8 radians per second and suspends offscreen or in a hidden tab; changing the reduced-motion preference pauses playback. Device pixel ratio is capped at 2. Missing WebGL2, shader compilation/link failures, and a lost graphics context produce distinct explanatory states. Removal releases the shader program, shader objects, vertex array, observers, and listeners.
The SVG fallback is an illustration of overlapping wave sources, not a screenshot of the computed field. The exact fragment source is exported by the shader module as ALK_INTERFERENCE_FRAGMENT for the test page’s source specimen.
This component currently renders its own two-source field. It does not accept an arbitrary shader path, execute untrusted shader code, or provide a general shader editor. The working study is on the test page.