PolyScene
The scene is the root of every PolyCSS render tree. It applies scene-level lighting and atlas options, then renders its children (typically meshes or individual polygons) in 3D space. <poly-scene> / PolyScene must always be nested inside a camera element (<poly-camera> / PolyCamera or the perspective variant): the camera owns the projection and orbital state.
It’s available as a custom element (<poly-scene>), via the imperative createPolyScene(host, opts) API, and as React / Vue components (<PolyScene>).
Scene props / attributes
Section titled “Scene props / attributes”(React / Vue prop names use camelCase; the <poly-scene> custom element accepts the kebab-case form, e.g. textureQuality → texture-quality.)
The React/Vue components and createPolyScene() support the full table. The <poly-scene> custom element supports directional-*, ambient-*, texture-lighting, texture-quality, auto-center, and implicit camera attributes; use the imperative API for options such as shadow, seamBleed, and strategies in vanilla.
| Prop | Type | Default | Description |
|---|---|---|---|
directionalLight | PolyDirectionalLight | None | Directional light source. |
ambientLight | PolyAmbientLight | None | Ambient fill light. |
textureLighting | "baked" | "dynamic" | "baked" | Whether texture lighting is rasterized into atlases or computed with CSS variables. |
textureQuality | number | "auto" | "auto" | Atlas bitmap budget and compositor sprite size. Auto caps large runtime bitmaps and uses a larger desktop sprite to avoid Safari/Firefox flattening artifacts; lower numeric values reduce texture memory and detail. |
seamBleed | number | "auto" | 1.5 | Solid-primitive overscan for detected shared seam edges. "auto" fits each edge from the polygon plan; numbers clamp the CSS-pixel amount. |
strategies | { disable?: ("b" | "i" | "u")[] } | None | Diagnostic override for render strategy selection. Disabled solid strategies fall through to <s> atlas slices; <s> cannot be disabled. |
autoCenter | boolean | false | Rotate around the content bbox center instead of world origin. Polygon data is not mutated. |
centerPolygons | Polygon[] | None | (Framework only.) Bbox source for autoCenter when renderable polygons live inside child meshes. |
shadow | { color?, opacity?, lift?, maxExtend? } | { color:"#000000", opacity:0.25, lift:0.05, maxExtend:2000 } | Appearance and SVG extent cap for cast shadows emitted by meshes with castShadow. |
polygons | Polygon[] | None | (Framework only.) Flat array of polygon objects rendered as direct children. Composes with JSX/slot children. |
children | None | None | Meshes, polygons, controls, helpers, selection wrappers, and transform controls. |
Camera state and input are set on the wrapping camera element (<poly-camera> / PolyCamera): rot-x, rot-y, zoom, distance. <poly-scene> carries no camera attributes. Add a child <poly-orbit-controls> / <PolyOrbitControls> to enable drag, wheel, or autorotate: see PolyOrbitControls.
Mesh props / attributes
Section titled “Mesh props / attributes”React/Vue <PolyMesh> supports the full table. The <poly-mesh> custom element currently supports src, mtl, mesh-resolution, position, scale, rotation, and auto-center; use scene.add(result, opts) for advanced vanilla mesh options such as castShadow.
| Prop | Type | Description |
|---|---|---|
id | string | Stable mesh identifier. Reflected as data-poly-mesh-id and exposed on mesh handles for selection / transform tools. |
src | string | URL to .obj, .glb, .gltf, or .vox. |
polygons | Polygon[] | Pre-parsed polygons (alternative to src). Framework only. |
position | Vec3 | [x, y, z] offset in scene space. |
scale | number | Vec3 | Uniform or per-axis scale. |
rotation | Vec3 | Euler rotation in degrees [x, y, z]. |
textureLighting | "baked" | "dynamic" | Per-mesh lighting mode override. Defaults to the scene value. |
textureQuality | number | "auto" | Atlas bitmap budget and compositor sprite size. React / Vue only; vanilla meshes inherit the scene’s texture-quality. |
seamBleed | number | "auto" | Per-mesh solid seam overscan. React / Vue only; vanilla meshes inherit the scene setting. |
atomicAtlas | boolean | Hold the previous atlas frame until the next frame is decoded, then swap atomically. React / Vue only. |
onFrameReady | () => void | Fires when an atomic atlas frame swaps to a ready one. React / Vue only. |
autoCenter | boolean | Shift the loaded mesh so its bounding-box center sits at the local origin before applying position. Useful when assets aren’t centered in their file coordinates. |
mtl | string | Companion .mtl URL for OBJ models. |
parseOptions | UseMeshOptions | Parser options forwarded to loadMesh; meshResolution defaults to "lossy". |
meshResolution | "lossless" | "lossy" | Top-level optimizer intent. Wins over parseOptions.meshResolution; defaults to "lossy". |
castShadow | boolean | Emit SVG cast shadows in both lighting modes; projections update when light, ground, or mesh geometry changes. |
fallback | ReactNode | Rendered while src is loading. (React / Vue only.) |
errorFallback | (error: Error) => ReactNode | Rendered if parse fails. (React / Vue only.) |
children | (polygon, index) => ReactNode | Per-polygon render prop / scoped slot. (React / Vue only.) |
Ground Props
Section titled “Ground Props”PolyGround is a React/Vue convenience component for a flat shadow-receiving plane.
| Prop | Type | Default | Description |
|---|---|---|---|
size | number | 6 | Side length in world units. |
z | number | 0 | World-space floor height. |
center | [number, number] | [0,0] | Ground center in world X/Y. |
color | string | "#7d848e" | Ground fill color. |
className / class | string | None | Additional CSS class. |
PolyDirectionalLight
Section titled “PolyDirectionalLight”interface PolyDirectionalLight { direction: [number, number, number]; // Direction the light shines toward color?: string; // Light color (default: "#ffffff") intensity?: number; // Directional intensity (default: 1)}
interface PolyAmbientLight { color?: string; // Ambient tint (default: "#ffffff") intensity?: number; // Ambient intensity (default: 0.4)}Scene Helpers
Section titled “Scene Helpers”Helpers render as ordinary scene children and are available in vanilla custom elements plus React/Vue components.
| Helper | Props | Description |
|---|---|---|
<poly-axes-helper> / PolyAxesHelper | size, thickness, negative, xColor, yColor, zColor | Draws red/green/blue world axes from the origin. |
<poly-directional-light-helper> / PolyDirectionalLightHelper | React/Vue: light, target, distance, size, color. Vanilla: direction, target, distance, size, color. | Draws a small marker along a directional light vector. |
Basic Scene
Section titled “Basic Scene”A scene with a dodecahedron at default camera angle.
<script type="module" src="https://esm.sh/@layoutit/polycss/elements"></script>
<poly-camera rot-x="65" rot-y="45"> <poly-scene> <poly-dodecahedron size="100" color="#a78bfa"></poly-dodecahedron> </poly-scene></poly-camera>import { PolyCamera, PolyScene, PolyDodecahedron } from "@layoutit/polycss-react";
export function App() { return ( <PolyCamera rotX={65} rotY={45}> <PolyScene> <PolyDodecahedron size={100} color="#a78bfa" /> </PolyScene> </PolyCamera> );}<template> <PolyCamera :rot-x="65" :rot-y="45"> <PolyScene> <PolyDodecahedron :size="100" color="#a78bfa" /> </PolyScene> </PolyCamera></template>
<script setup lang="ts">import { PolyCamera, PolyScene, PolyDodecahedron } from "@layoutit/polycss-vue";</script>Scene with Camera and Lighting
Section titled “Scene with Camera and Lighting”import { PolyPerspectiveCamera, PolyScene, PolyTorus, PolyBox } from "@layoutit/polycss-react";
<PolyPerspectiveCamera perspective={1000} rotX={65} rotY={45}> <PolyScene directionalLight={{ direction: [0.5, -0.7, 0.6], color: "#ffe4a8" }} ambientLight={{ intensity: 0.4 }} > <PolyTorus color="#4ecdc4" position={[0, 0, 0]} /> <PolyBox size={60} color="#ffd166" position={[8, 0, 0]} /> </PolyScene></PolyPerspectiveCamera>Cast Shadows
Section titled “Cast Shadows”Shadows are SVG-projected surfaces. They work in both lighting modes; textureLighting controls surface shading, while shadow geometry reprojects when the light or scene geometry changes.
import { PolyCamera, PolyScene, PolyGround, PolyMesh } from "@layoutit/polycss-react";
<PolyCamera rotX={65} rotY={45}> <PolyScene textureLighting="dynamic" directionalLight={{ direction: [0.4, -0.6, 1], intensity: 1 }} shadow={{ opacity: 0.28, lift: 0.04 }} > <PolyGround size={8} color="#d8d2c7" /> <PolyMesh src="/model.glb" castShadow /> </PolyScene></PolyCamera>Strategy Diagnostics
Section titled “Strategy Diagnostics”Use strategies.disable when you need to compare paths or isolate browser rendering issues.
<PolyScene strategies={{ disable: ["b", "i", "u"] }}> <PolyMesh src="/model.glb" /></PolyScene>Multiple Meshes
Section titled “Multiple Meshes”<PolyCamera rotX={65} rotY={45}> <PolyScene> <PolyIcosahedron size={80} color="#ff6644" position={[0, 0, 0]} /> <PolyBox size={60} color="#7dd3fc" position={[10, 0, 0]} /> </PolyScene></PolyCamera>Flat Polygon Array
Section titled “Flat Polygon Array”Pass a polygons array directly to render static geometry without a file loader.
const polygons: Polygon[] = [ { vertices: [[0,0,0],[1,0,0],[0,1,0]], color: "#f00" }, { vertices: [[2,0,0],[3,0,0],[2,1,0]], color: "#00f" },];
<PolyCamera> <PolyScene polygons={polygons} /></PolyCamera>Related
Section titled “Related”- PolyCamera: Camera state and projection.
- Loading Meshes: OBJ, STL, glTF, GLB, VOX, MTL loading.
- Per-polygon Interaction: Using
Polyfor interactive per-polygon control. - Performance: Merge modes and DOM tuning.