Skip to main content
Filament provides native C++ APIs for desktop platforms including Linux, macOS, and Windows. This guide covers platform-specific SwapChain creation and backend configuration.

Supported Platforms

Filament supports the following desktop operating systems:

Linux

  • X11
  • Wayland
  • OpenGL 4.1+
  • Vulkan 1.0+
  • WebGPU

macOS

  • OpenGL 4.1+
  • Metal
  • Vulkan (via MoltenVK)
  • WebGPU

Windows

  • OpenGL 4.1+
  • Vulkan 1.0+
  • WebGPU

Installation

From Binary Releases

Download prebuilt releases from GitHub Releases:
# Linux
wget https://github.com/google/filament/releases/download/v1.69.4/filament-v1.69.4-linux.tgz
tar -xzf filament-v1.69.4-linux.tgz

# macOS
wget https://github.com/google/filament/releases/download/v1.69.4/filament-v1.69.4-mac.tgz
tar -xzf filament-v1.69.4-mac.tgz

# Windows
curl -LO https://github.com/google/filament/releases/download/v1.69.4/filament-v1.69.4-windows.tgz
tar -xzf filament-v1.69.4-windows.tgz

Building from Source

See the Building Guide for instructions on building from source.

Basic Setup

1

Include Filament headers

#include <filament/Engine.h>
#include <filament/SwapChain.h>
#include <filament/Renderer.h>
#include <filament/View.h>
#include <filament/Scene.h>
#include <filament/Camera.h>
#include <utils/EntityManager.h>
2

Create the Engine

using namespace filament;

// Create the engine with optional backend selection
Engine* engine = Engine::create(Engine::Backend::DEFAULT);
3

Create rendering components

Renderer* renderer = engine->createRenderer();
Scene* scene = engine->createScene();
View* view = engine->createView();

utils::Entity cameraEntity = utils::EntityManager::get().create();
Camera* camera = engine->createCamera(cameraEntity);

view->setCamera(camera);
view->setScene(scene);

Platform-Specific SwapChain Creation

The SwapChain is created from a native window handle, which varies by platform.
#include <Windows.h>
#include <filament/SwapChain.h>

// Get HWND from your windowing library (SDL2, GLFW, etc.)
HWND hwnd = /* your window handle */;

// Create SwapChain
SwapChain* swapChain = engine->createSwapChain((void*)hwnd);
Using SDL2:
#include <SDL_syswm.h>

void* getNativeWindow(SDL_Window* sdlWindow) {
    SDL_SysWMinfo wmi;
    SDL_VERSION(&wmi.version);
    SDL_GetWindowWMInfo(sdlWindow, &wmi);
    return (void*)wmi.info.win.window;
}

SwapChain* swapChain = engine->createSwapChain(
    getNativeWindow(sdlWindow)
);

Rendering Loop

A typical rendering loop:
while (!shouldClose) {
    // Process window events
    pollEvents();
    
    // Update scene transformations
    updateScene(engine, view, scene);
    
    // Render frame
    if (renderer->beginFrame(swapChain)) {
        renderer->render(view);
        renderer->endFrame();
    }
}

Complete Example

Minimal triangle example:
hellotriangle.cpp
#include <filament/Engine.h>
#include <filament/Renderer.h>
#include <filament/Scene.h>
#include <filament/View.h>
#include <filament/Camera.h>
#include <filament/SwapChain.h>
#include <filament/VertexBuffer.h>
#include <filament/IndexBuffer.h>
#include <filament/Material.h>
#include <filament/RenderableManager.h>
#include <utils/EntityManager.h>

using namespace filament;
using namespace filament::math;

struct Vertex {
    float2 position;
    uint32_t color;
};

static const Vertex TRIANGLE_VERTICES[3] = {
    {{1, 0}, 0xffff0000u},
    {{cos(M_PI * 2 / 3), sin(M_PI * 2 / 3)}, 0xff00ff00u},
    {{cos(M_PI * 4 / 3), sin(M_PI * 4 / 3)}, 0xff0000ffu},
};

static constexpr uint16_t TRIANGLE_INDICES[3] = {0, 1, 2};

int main() {
    Engine* engine = Engine::create();
    SwapChain* swapChain = engine->createSwapChain(nativeWindow);
    Renderer* renderer = engine->createRenderer();
    Scene* scene = engine->createScene();
    View* view = engine->createView();
    
    auto cameraEntity = utils::EntityManager::get().create();
    Camera* camera = engine->createCamera(cameraEntity);
    view->setCamera(camera);
    view->setScene(scene);
    
    // Create vertex buffer
    VertexBuffer* vb = VertexBuffer::Builder()
        .vertexCount(3)
        .bufferCount(1)
        .attribute(VertexAttribute::POSITION, 0,
                   VertexBuffer::AttributeType::FLOAT2, 0, 12)
        .attribute(VertexAttribute::COLOR, 0,
                   VertexBuffer::AttributeType::UBYTE4, 8, 12)
        .normalized(VertexAttribute::COLOR)
        .build(*engine);
    
    vb->setBufferAt(*engine, 0,
        VertexBuffer::BufferDescriptor(TRIANGLE_VERTICES, 36));
    
    // Create index buffer
    IndexBuffer* ib = IndexBuffer::Builder()
        .indexCount(3)
        .bufferType(IndexBuffer::IndexType::USHORT)
        .build(*engine);
    
    ib->setBuffer(*engine,
        IndexBuffer::BufferDescriptor(TRIANGLE_INDICES, 6));
    
    // Load material and create renderable
    Material* mat = Material::Builder()
        .package(MATERIAL_DATA, MATERIAL_SIZE)
        .build(*engine);
    
    auto renderable = utils::EntityManager::get().create();
    RenderableManager::Builder(1)
        .boundingBox({{-1, -1, -1}, {1, 1, 1}})
        .material(0, mat->getDefaultInstance())
        .geometry(0, RenderableManager::PrimitiveType::TRIANGLES,
                  vb, ib, 0, 3)
        .build(*engine, renderable);
    
    scene->addEntity(renderable);
    
    // Render loop
    while (!shouldClose) {
        if (renderer->beginFrame(swapChain)) {
            renderer->render(view);
            renderer->endFrame();
        }
    }
    
    // Cleanup
    engine->destroy(renderable);
    engine->destroy(mat);
    engine->destroy(vb);
    engine->destroy(ib);
    engine->destroy(renderer);
    engine->destroy(view);
    engine->destroy(scene);
    engine->destroyCameraComponent(cameraEntity);
    utils::EntityManager::get().destroy(cameraEntity);
    engine->destroy(swapChain);
    Engine::destroy(&engine);
    
    return 0;
}

Backend Selection

Choose a specific rendering backend:
// Default (automatic selection)
Engine* engine = Engine::create();

// Explicit backend
Engine* engine = Engine::create(Engine::Backend::VULKAN);

// Available backends:
// - Engine::Backend::DEFAULT
// - Engine::Backend::OPENGL
// - Engine::Backend::VULKAN
// - Engine::Backend::METAL (macOS only)
// - Engine::Backend::NOOP (testing)

Window Management Libraries

Filament works with popular windowing libraries:
#include <SDL.h>
#include <SDL_syswm.h>

SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow(
    "Filament",
    SDL_WINDOWPOS_CENTERED,
    SDL_WINDOWPOS_CENTERED,
    1280, 720,
    SDL_WINDOW_SHOWN
);

void* nativeWindow = getNativeWindow(window);
SwapChain* swapChain = engine->createSwapChain(nativeWindow);

Feature Levels

Desktop platforms support higher feature levels:
// Query the active feature level
Engine::FeatureLevel level = engine->getActiveFeatureLevel();

// Desktop typically supports FEATURE_LEVEL_3
// which enables all advanced features

Performance Tips

Always destroy the SwapChain before destroying the window to avoid crashes.
// Correct cleanup order
engine->destroy(swapChain);
destroyWindow(); // SDL_DestroyWindow, glfwDestroyWindow, etc.
Engine::destroy(&engine);

Next Steps

FilamentApp

Use the FilamentApp helper library

Multiple Windows

Render to multiple windows

ImGui Integration

Add debug UI with Dear ImGui

Performance

Optimize desktop rendering

Build docs developers (and LLMs) love