Primitive Geometry

Cube, sphere, cylinder, and plane. This example shows how to create basic shapes with simple materials.

Transport

You are viewing: Browser (WASM) · Switch

In the browser, use a canvas with id vulfram-canvas.

Key steps

1. Create the camera and the light.

2. Generate geometry with createGeometry.

3. Create simple materials with color textures.

4. Instantiate models and position them with updateTransform.

Full example

Use this snippet as a base and tweak each primitive to experiment.

ts
import {
  initEngine,
  createWorld,
  createWindow,
  createEntity,
  createCamera,
  createLight,
  createGeometry,
  createMaterial,
  createModel,
  createTexture,
  updateTransform,
  tick,
} from '@vulfram/engine';
import { initWasmTransport, transportWasm } from '@vulfram/transport-wasm';

const WINDOW_ID = 1;

function createColorMaterial(color: [number, number, number, number]): number {
  const texId = createTexture(WINDOW_ID, {
    source: { type: 'color', color },
    srgb: true,
  });
  return createMaterial(WINDOW_ID, {
    kind: 'standard',
    options: {
      type: 'standard',
      content: {
        baseColor: [1, 1, 1, 1],
        surfaceType: 'opaque',
        baseTexId: texId,
        baseSampler: 'linear-clamp',
        flags: 0,
      },
    },
  });
}

async function boot() {
  await initWasmTransport();
  initEngine({ transport: transportWasm });
  createWorld(WINDOW_ID);
  createWindow(WINDOW_ID, {
    title: 'Primitives',
    size: [1100, 700],
    position: [0, 0],
    canvasId: 'vulfram-canvas',
  });

  const camera = createEntity(WINDOW_ID);
  updateTransform(WINDOW_ID, camera, {
    position: [0, 3, 12],
    rotation: [0, 0, 0, 1],
    scale: [1, 1, 1],
  });
  createCamera(WINDOW_ID, camera, { kind: 'perspective', near: 0.1, far: 100.0 });

  const light = createEntity(WINDOW_ID);
  updateTransform(WINDOW_ID, light, {
    position: [3, 6, 8],
    rotation: [0, 0, 0, 1],
    scale: [1, 1, 1],
  });
  createLight(WINDOW_ID, light, { kind: 'point', intensity: 16, range: 40 });

  const cubeGeom = createGeometry(WINDOW_ID, { type: 'primitive', shape: 'cube' });
  const sphereGeom = createGeometry(WINDOW_ID, {
    type: 'primitive',
    shape: 'sphere',
    options: { radius: 0.9, sectors: 24, stacks: 16 },
  });
  const cylinderGeom = createGeometry(WINDOW_ID, {
    type: 'primitive',
    shape: 'cylinder',
    options: { radius: 0.6, height: 2.2, sectors: 24 },
  });
  const planeGeom = createGeometry(WINDOW_ID, {
    type: 'primitive',
    shape: 'plane',
    options: { size: [14, 14, 1], subdivisions: 1 },
  });

  const grayMat = createColorMaterial([0.85, 0.86, 0.9, 1]);
  const blueMat = createColorMaterial([0.3, 0.55, 0.95, 1]);
  const amberMat = createColorMaterial([1, 0.7, 0.2, 1]);
  const floorMat = createColorMaterial([0.15, 0.15, 0.18, 1]);

  const cube = createEntity(WINDOW_ID);
  updateTransform(WINDOW_ID, cube, { position: [-3.2, 0, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  createModel(WINDOW_ID, cube, { geometryId: cubeGeom, materialId: grayMat, castShadow: true, receiveShadow: true });

  const sphere = createEntity(WINDOW_ID);
  updateTransform(WINDOW_ID, sphere, { position: [0, 0, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  createModel(WINDOW_ID, sphere, { geometryId: sphereGeom, materialId: blueMat, castShadow: true, receiveShadow: true });

  const cylinder = createEntity(WINDOW_ID);
  updateTransform(WINDOW_ID, cylinder, { position: [3.2, 0, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  createModel(WINDOW_ID, cylinder, { geometryId: cylinderGeom, materialId: amberMat, castShadow: true, receiveShadow: true });

  const floor = createEntity(WINDOW_ID);
  updateTransform(WINDOW_ID, floor, { position: [0, -2, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  createModel(WINDOW_ID, floor, { geometryId: planeGeom, materialId: floorMat, receiveShadow: true });

  let last = performance.now();
  function frame(now: number) {
    const delta = now - last;
    last = now;
    tick(now, delta);
    requestAnimationFrame(frame);
  }
  requestAnimationFrame(frame);
}

boot().catch(console.error);
Live demo canvas