Skip to main content
Filament for Web provides a WebAssembly module with JavaScript bindings for browser-based rendering. It supports WebGL 2.0 on all modern browsers and WebGPU on compatible platforms.

Installation

Via npm

Install Filament.js from npm:
npm install filament
yarn add filament

Via CDN

Load directly from a CDN:
<script src="https://unpkg.com/filament@1.69.4/filament.js"></script>
<script src="https://cdn.jsdelivr.net/npm/filament@1.69.4/filament.js"></script>

Supported Backends

Supported on all modern browsers:
  • Chrome 56+
  • Firefox 51+
  • Safari 15+
  • Edge 79+
WebGL 2.0 is the default and most compatible backend.

Basic Setup

1

Create a canvas element

index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <style>
        body { margin: 0; overflow: hidden; }
        canvas { width: 100%; height: 100%; }
    </style>
</head>
<body>
    <canvas id="filament-canvas"></canvas>
    <script src="filament.js"></script>
    <script src="app.js"></script>
</body>
</html>
2

Initialize Filament

Filament must be initialized asynchronously:
app.js
Filament.init(['material.filamat'], () => {
    // Set up namespaces for convenience
    window.VertexAttribute = Filament.VertexAttribute;
    window.AttributeType = Filament.VertexBuffer$AttributeType;
    window.PrimitiveType = Filament.RenderableManager$PrimitiveType;
    window.IndexType = Filament.IndexBuffer$IndexType;
    window.Projection = Filament.Camera$Projection;
    
    // Start the app
    const canvas = document.getElementById('filament-canvas');
    window.app = new App(canvas);
});
3

Create the rendering context

app.js
class App {
    constructor(canvas) {
        this.canvas = canvas;
        
        // Create engine
        this.engine = Filament.Engine.create(canvas);
        
        // Create rendering components
        this.scene = this.engine.createScene();
        this.swapChain = this.engine.createSwapChain();
        this.renderer = this.engine.createRenderer();
        this.camera = this.engine.createCamera(
            Filament.EntityManager.get().create()
        );
        
        this.view = this.engine.createView();
        this.view.setCamera(this.camera);
        this.view.setScene(this.scene);
        
        this.resize();
        window.addEventListener('resize', () => this.resize());
    }
}

Creating Geometry

Create vertex and index buffers:
class App {
    constructor(canvas) {
        // ... previous setup ...
        
        this.createTriangle();
    }
    
    createTriangle() {
        // Vertex data
        const TRIANGLE_POSITIONS = new Float32Array([
            1, 0,
            Math.cos(Math.PI * 2 / 3), Math.sin(Math.PI * 2 / 3),
            Math.cos(Math.PI * 4 / 3), Math.sin(Math.PI * 4 / 3),
        ]);
        
        const TRIANGLE_COLORS = new Uint32Array([
            0xffff0000,
            0xff00ff00,
            0xff0000ff
        ]);
        
        // Create vertex buffer
        this.vertexBuffer = Filament.VertexBuffer.Builder()
            .vertexCount(3)
            .bufferCount(2)
            .attribute(
                VertexAttribute.POSITION,
                0,
                AttributeType.FLOAT2,
                0,
                8
            )
            .attribute(
                VertexAttribute.COLOR,
                1,
                AttributeType.UBYTE4,
                0,
                4
            )
            .normalized(VertexAttribute.COLOR)
            .build(this.engine);
        
        this.vertexBuffer.setBufferAt(this.engine, 0, TRIANGLE_POSITIONS);
        this.vertexBuffer.setBufferAt(this.engine, 1, TRIANGLE_COLORS);
        
        // Create index buffer
        this.indexBuffer = Filament.IndexBuffer.Builder()
            .indexCount(3)
            .bufferType(IndexType.USHORT)
            .build(this.engine);
        
        this.indexBuffer.setBuffer(
            this.engine,
            new Uint16Array([0, 1, 2])
        );
    }
}

Loading Materials

Load precompiled material files:
const material = this.engine.createMaterial('material.filamat');
const materialInstance = material.getDefaultInstance();

Creating Renderables

Build a renderable entity and add it to the scene:
this.triangle = Filament.EntityManager.get().create();

Filament.RenderableManager.Builder(1)
    .boundingBox({
        center: [-1, -1, -1],
        halfExtent: [1, 1, 1]
    })
    .material(0, materialInstance)
    .geometry(
        0,
        PrimitiveType.TRIANGLES,
        this.vertexBuffer,
        this.indexBuffer
    )
    .build(this.engine, this.triangle);

this.scene.addEntity(this.triangle);

Rendering Loop

Use requestAnimationFrame for the render loop:
class App {
    constructor(canvas) {
        // ... setup ...
        
        this.render = this.render.bind(this);
        window.requestAnimationFrame(this.render);
    }
    
    render() {
        // Animate the triangle
        const radians = Date.now() / 1000;
        const transform = mat4.fromRotation(
            mat4.create(),
            radians,
            [0, 0, 1]
        );
        
        const tcm = this.engine.getTransformManager();
        const inst = tcm.getInstance(this.triangle);
        tcm.setTransform(inst, transform);
        inst.delete();
        
        // Render the frame
        this.renderer.render(this.swapChain, this.view);
        
        // Schedule next frame
        window.requestAnimationFrame(this.render);
    }
}

Handling Window Resize

Update the viewport and camera projection:
resize() {
    const dpr = window.devicePixelRatio;
    const width = this.canvas.width = window.innerWidth * dpr;
    const height = this.canvas.height = window.innerHeight * dpr;
    
    this.view.setViewport([0, 0, width, height]);
    
    const aspect = width / height;
    this.camera.setProjection(
        Projection.ORTHO,
        -aspect, aspect,
        -1, 1,
        0, 1
    );
}

Complete Example

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Filament Triangle</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <style>
        body { margin: 0; overflow: hidden; }
        canvas { touch-action: none; width: 100%; height: 100%; }
    </style>
</head>
<body>
    <canvas></canvas>
    <script src="filament.js"></script>
    <script src="gl-matrix-min.js"></script>
    <script src="app.js"></script>
</body>
</html>

Loading Assets

Filament.init() can preload multiple assets:
Filament.init([
    'materials/base.filamat',
    'materials/glass.filamat',
    'models/scene.gltf',
    'textures/environment.ktx'
], () => {
    // All assets are loaded
    const material1 = engine.createMaterial('materials/base.filamat');
    const material2 = engine.createMaterial('materials/glass.filamat');
});

Memory Management

Manually delete temporary objects to avoid memory leaks:
// Delete transform instances
const tcm = engine.getTransformManager();
const inst = tcm.getInstance(entity);
tcm.setTransform(inst, transform);
inst.delete(); // Important!

// Destroy resources when done
engine.destroy(vertexBuffer);
engine.destroy(indexBuffer);
engine.destroy(material);
engine.destroy(renderable);

Module Bundlers

Using with Webpack, Rollup, or Vite:
import { init } from 'filament';

init(['material.filamat'], () => {
    // Your app code
});
Make sure to copy the WASM files to your output directory.

TypeScript Support

Filament includes TypeScript definitions:
import * as Filament from 'filament';

Filament.init(['material.filamat'], () => {
    const canvas = document.getElementById('canvas') as HTMLCanvasElement;
    const engine = Filament.Engine.create(canvas);
    // Type checking and autocomplete work!
});

Performance Tips

  • Minimize JavaScript/WebAssembly boundary crossings
  • Reuse buffers and materials when possible
  • Use VertexBuffer.setBufferAt() instead of recreating buffers
  • Delete temporary objects returned by the API

Browser Support Matrix

BrowserWebGL 2.0WebGPUStatus
Chrome 56+✅ (113+)Full support
Firefox 51+🔶 ExperimentalFull support
Safari 15+🔶 ExperimentalFull support
Edge 79+✅ (113+)Full support

Next Steps

glTF Viewer

Load 3D models in the browser

IBL

Set up image-based lighting

Post-Processing

Add bloom, DOF, and tone mapping

Web Samples

View live demos

Build docs developers (and LLMs) love