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,
  Mount,
  World3D,
  createWindow,
  tick,
} from '@vulfram/engine';
import { initWasmTransport, transportWasm } from '@vulfram/transport-browser';


function createSurfaceMaterial(label: string, color: [number, number, number, number], surfaceType: 'opaque' | 'masked' | 'transparent'): number {
  const texId = World3D.create3DTexture(worldId, { source: { type: 'color', color }, srgb: true, label: label + ' Texture' });
  return World3D.create3DMaterial(worldId, {
    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 });
  const worldId = World3D.create3DWorld();
  const { windowId } = createWindow({
    title: 'Surface Types',
    size: [1100, 700],
    position: [0, 0],
    canvasId: 'vulfram-canvas',
  });
Mount.mountWorldToWindow(worldId, windowId);

  const camera = World3D.create3DEntity(worldId);
  World3D.update3DTransform(worldId, camera, { position: [0, 2, 8], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  World3D.create3DCamera(worldId, camera, { kind: 'perspective', near: 0.1, far: 100.0 });

  const light = World3D.create3DEntity(worldId);
  World3D.update3DTransform(worldId, light, { position: [2, 4, 6], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  World3D.create3DLight(worldId, light, { kind: 'point', intensity: 14, range: 30 });

  const planeGeom = World3D.create3DGeometry(worldId, { 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 = World3D.create3DEntity(worldId);
  World3D.update3DTransform(worldId, opaque, { position: [-3.5, 0, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  World3D.create3DModel(worldId, opaque, { geometryId: planeGeom, materialId: opaqueMat });

  const masked = World3D.create3DEntity(worldId);
  World3D.update3DTransform(worldId, masked, { position: [0, 0, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  World3D.create3DModel(worldId, masked, { geometryId: planeGeom, materialId: maskedMat });

  const transparent = World3D.create3DEntity(worldId);
  World3D.update3DTransform(worldId, transparent, { position: [3.5, 0, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] });
  World3D.create3DModel(worldId, 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