Architecture & Code Showcases
Small World Engine has a modular design and favors composition over deep inheritance. Below is an overview of the key classes, interfaces, and parameters you'll work with day to day, along with concrete code examples to get started.
API Reference
For a complete list of all classes, methods, and type declarations (including constructor parameters), open the auto-generated API Reference.
1. Scene Graph (Object3D)
The heart of the engine is the Object3D class. Everything that exists in the world (meshes, cameras, virtual anchors) is an Object3D or inherits from it. It manages local and global transformation matrices, geometry, and material.
Showcase: Creating and placing an object
import { Object3D, Cube, StandardMaterial, Color } from "@small-world/engine";
const player = new Object3D("Player");
// Position (X=Right, Y=Up, Z=Backward)
player.position.set(0, 1, 0);
// Scale and rotation
player.scale.set(2, 2, 2);
player.rotation.y = Math.PI / 4; // 45 degrees
// Assign geometry and material
player.geometry = new Cube({ size: 1 }).getGeometryData();
player.material = new StandardMaterial({
color: Color.RED,
metallic: 0.1,
roughness: 0.8,
});
// Attach child objects (hierarchy)
const weapon = new Object3D("Weapon");
weapon.position.set(1, 0, 0); // Relative to the player!
player.add(weapon);
// Add to the scene
this.scene.add(player);2. Cameras & Behaviors
The engine uses a unified camera architecture. The base Camera is parameterized by a projection (PerspectiveProjection or OrthographicProjection) and driven dynamically through the Behavior system. Procedural, one-shot camera effects (shake, flash, ...) are a separate mechanism: the CameraEffect system, added via camera.addEffect() or camera.applyEffect() rather than addBehavior().
Showcase: Camera with controller and shake effect
import { Camera, PerspectiveProjection, FirstPersonController, ShakeEffect } from "@small-world/engine";
// Create a camera with a perspective projection
const camera = new Camera(new PerspectiveProjection({ fov: 60, near: 0.1, far: 1000 }));
// Attach a controller directly as a Behavior
camera.addBehavior(
new FirstPersonController({
moveSpeed: 10.0,
lookSensitivity: 0.002,
})
);
// Add a procedural trauma-based camera shake effect for impacts
camera.addEffect(new ShakeEffect(0.5, 0.5));3. Materials & Shaders (PBR & built-in presets)
Small World uses a hybrid rendering pipeline (WebGPU, WebGL2, WebGL1) built on the Cook-Torrance BRDF model with linear color space and sRGB gamma correction.
Key material families
StandardMaterial: Core PBR material withalbedo,metallic,roughness, and diffuse/normal/roughness map slots.GlassMaterial: Real-time screen-space refraction (SSR) with configurableiorand volumetric absorption.SpriteMaterial: Camera-facing 2D/2.5D billboard material.- Wave family (ADR 0013):
OpenWaterMaterial: Realistic ocean water with Gerstner waves and opaque depth fade (soft shorelines).StylizedWaterMaterial: Stylized/toon water with adjustable edge foam and cel shading.
- Flow family (ADR 0013):
LavaMaterial: Opaque, glowing molten rock with adjustable emissive intensity and noise-driven viscosity.SlimeMaterial: Translucent, viscous preset with a subtle glowing edge rim.
Showcase: Lava material with emissive glow
import { LavaMaterial, Color, Object3D, Plane } from "@small-world/engine";
const lava = new Object3D("LavaLake");
lava.geometry = new Plane({ width: 50, height: 50, widthSegments: 32, heightSegments: 32 }).getGeometryData();
lava.material = new LavaMaterial({
color: new Color(0.25, 0.03, 0.0),
emissiveColor: new Color(1.0, 0.35, 0.05),
emissiveStrength: 2.0,
flowSpeed: 0.4,
});
this.scene.add(lava);4. Behaviors & State Machines (FSM)
Complex logic should not be crammed into one giant update() loop. Instead, use the Behavior system to attach isolated blocks of logic (components) to an Object3D.
Showcase: A Pulse behavior
import { Behavior, Object3D } from "@small-world/engine";
export class PulseBehavior extends Behavior {
private _speed: number;
private _baseScale: number;
private _elapsed: number = 0;
constructor(speed: number = 2.0) {
super();
this._speed = speed;
this._baseScale = 1.0;
}
// Called when the behavior is attached to the object via obj.addBehavior()
public override onAttach(target: Object3D): void {
this._baseScale = target.scale.x;
}
// Called automatically every frame by the Scene, receiving only deltaTime
public override update(deltaTime: number): void {
if (!this.target) return;
this._elapsed += deltaTime;
// Compute a sinusoidal pulse
const scale = this._baseScale + Math.sin(this._elapsed * this._speed) * 0.2;
this.target.scale.set(scale, scale, scale);
}
}
// Usage:
const heart = new Object3D("Heart");
heart.addBehavior(new PulseBehavior(5.0));As states grow more complex (e.g. IDLE -> WALK -> ATTACK), use the built-in StateMachine module, which integrates seamlessly into behaviors via StateMachineBehavior.
5. Resource Management & Garbage Collection
Unlike older graphics engines, where dispose() must be called manually on geometries, textures, and materials to avoid GPU memory leaks, Small World uses automated internal reference counting.
How it works
Every geometry buffer, shader program, and texture is tracked by the active renderer (WebGL1, WebGL2, or WebGPU). When an Object3D is removed from the Scene, the engine decrements the reference counters for the object's resources. Once a resource's reference counter reaches zero, the engine automatically queues it for deletion and safely destroys the underlying GPU object.
// Adding an object increments the reference counters for its geometry and material textures
this.scene.add(myObject);
// ... later ...
// Removing the object decrements the reference counters.
// If no other object uses the same geometry/textures, they are automatically freed from VRAM!
this.scene.remove(myObject);(Note: RenderTarget textures are exempt from this automated cleanup, since their lifecycle is managed explicitly by the render pipeline rather than by individual objects.)