Surface Types

Compare opaque, masked, and transparent surfaces to understand how blending affects the final look.

Transport

You are viewing: Browser (WASM) · Switch

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

Key steps

1. Create three materials with different surfaceType values.

2. Use alpha colors to notice the difference between masked and transparent.

3. Compare the result side by side.

Full example

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 createSurfaceMaterial(label: string, color: [number, number, number, number], surfaceType: 'opaque' | 'masked' | 'transparent'): number {
  const texId = createTexture(WINDOW_ID, { source: { type: 'color', color }, srgb: true, label: label + ' Texture' });
  return createMaterial(WINDOW_ID, {
    kind: 'standard',
    options: {
      type: 'standard',
      content: {
        baseColor: [1, 1, 1, 1],
        surfaceType,
        baseTexId: texId,
        baseSampler: 'linear-clamp',
        flags: 0,
      },
    },
  });
}

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

  const camera = createEntity(WINDOW_ID);
  updateTransform(WINDOW_ID, camera, { position: [0, 2, 8], 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: [2, 4, 6], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  createLight(WINDOW_ID, light, { kind: 'point', intensity: 14, range: 30 });

  const planeGeom = createGeometry(WINDOW_ID, { type: 'primitive', shape: 'plane', options: { size: [3, 3, 1], subdivisions: 1 } });

  const opaqueMat = createSurfaceMaterial('Opaque', [0.9, 0.2, 0.2, 1], 'opaque');
  const maskedMat = createSurfaceMaterial('Masked', [0.2, 0.8, 0.3, 0.4], 'masked');
  const transparentMat = createSurfaceMaterial('Transparent', [0.2, 0.5, 0.9, 0.35], 'transparent');

  const opaque = createEntity(WINDOW_ID);
  updateTransform(WINDOW_ID, opaque, { position: [-3.5, 0, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  createModel(WINDOW_ID, opaque, { geometryId: planeGeom, materialId: opaqueMat });

  const masked = createEntity(WINDOW_ID);
  updateTransform(WINDOW_ID, masked, { position: [0, 0, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  createModel(WINDOW_ID, masked, { geometryId: planeGeom, materialId: maskedMat });

  const transparent = createEntity(WINDOW_ID);
  updateTransform(WINDOW_ID, transparent, { position: [3.5, 0, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  createModel(WINDOW_ID, transparent, { geometryId: planeGeom, materialId: transparentMat });

  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