Skip to content

PolyScene

The scene is the root of every polycss render tree. It sets up CSS 3D perspective, accepts camera props, applies directional lighting, and renders its children (typically meshes or individual polygons) in 3D space.

It’s available as a custom element (<poly-scene>), via the imperative createPolyScene(host, opts) API, and as React / Vue components (<PolyScene>).

(React / Vue prop names use camelCase; the <poly-scene> custom element accepts the kebab-case form, e.g. rotXrot-x.)

PropTypeDefaultDescription
perspectivenumber1000CSS perspective distance in pixels. Higher values feel flatter (more isometric); lower values exaggerate depth.
rotXnumber65Camera rotation around the X axis in degrees.
rotYnumber45Camera rotation around the Y axis in degrees (0–360).
zoomnumber1Scene scale factor.
directionalLightDirectionalLightDirectional light source. See DirectionalLight.
atlasScalenumber1Raster scale for generated atlas pages. Lower values reduce texture memory and detail.
polygonsPolygon[](Framework only.) Flat array of polygon objects rendered as direct children. Composes with JSX/slot children.
merge"off" | "auto""off"Merge strategy. "auto" merges coplanar same-material polygons before rendering.
interactivebooleanfalseEnable pointer-drag camera rotation.
autoRotateAutoRotateOptionAuto-rotate camera. Pass true for default Y-axis rotation, a speed number, or { axis, speed, pauseOnInteraction }.
children<poly-mesh> / <poly-polygon> (vanilla) or <PolyMesh> / <Poly> (React / Vue).

(<poly-mesh> accepts the same fields as <PolyMesh>; kebab-case attributes map to camelCase props.)

PropTypeDescription
srcstringURL to .obj, .glb, or .gltf.
polygonsPolygon[]Pre-parsed polygons (alternative to src). Framework only.
positionVec3[x, y, z] offset in scene space.
scalenumber | Vec3Uniform or per-axis scale.
rotationVec3Euler rotation in degrees [x, y, z].
atlasScalenumberRaster scale for generated atlas pages. React / Vue only; vanilla meshes inherit the scene’s atlas-scale.
autoCenterbooleanShift 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.
parseOptionsObjParseOptions | GltfParseOptionsParser options forwarded to parseObj or parseGltf.
fallbackReactNodeRendered while src is loading. (React / Vue only.)
errorFallback(error: Error) => ReactNodeRendered if parse fails. (React / Vue only.)
children(polygon, index) => ReactNodePer-polygon render prop / scoped slot. (React / Vue only.)
interface DirectionalLight {
direction: [number, number, number]; // Direction the light shines toward (normalized)
color?: string; // Light color (default: "#ffffff")
ambientColor?: string; // Ambient light tint (default: "#ffffff")
ambient?: number; // Ambient intensity 0–1 (default: 0.4)
}

A scene with a single GLB mesh at default camera angle.

<script type="module" src="https://esm.sh/polycss/elements"></script>
<poly-scene>
<poly-mesh src="/cottage.glb"></poly-mesh>
</poly-scene>
<PolyScene
perspective={1000}
rotX={65}
rotY={45}
directionalLight={{
direction: [0.5, -0.7, 0.6],
color: "#ffe4a8",
ambient: 0.4,
}}
>
<PolyMesh src="/cottage.glb" position={[0, 0, 0]} />
<PolyMesh src="/tree.glb" position={[8, 0, 0]} scale={0.5} />
</PolyScene>
<PolyScene rotX={65} rotY={45}>
<PolyMesh src="/cottage.glb" position={[0, 0, 0]} />
<PolyMesh src="/tree.glb" position={[8, 0, 0]} scale={0.5} />
</PolyScene>

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" },
];
<PolyScene polygons={polygons} />