Skip to main content
Filament supports iOS 11.0 and above with both Metal (preferred) and OpenGL ES backends. This guide covers installation via CocoaPods and platform-specific setup.

Installation

CocoaPods

Add Filament to your iOS project using CocoaPods:
Podfile
pod 'Filament', '~> 1.69.4'
Then run:
pod install

Manual Installation

Alternatively, download the iOS release from GitHub Releases and link the frameworks manually.

Available Subspecs

Filament’s CocoaPod includes several subspecs:
SubspecDescription
filamentCore rendering engine
filamatRuntime material compiler
gltfio_coreglTF 2.0 loading
camutilsCamera manipulation utilities
viewerHigh-level glTF viewer
ktxreaderKTX texture loading

Backend Selection

Filament supports two rendering backends on iOS:

Setting Up the View

1

Create a custom UIView

Create a view that uses either CAMetalLayer or CAEAGLLayer:
FilamentView.h
#import <UIKit/UIKit.h>

@interface FilamentView : UIView
@end
2

Configure the layer class

Override the layerClass property to specify the backing layer:
FilamentView.m
#import "FilamentView.h"

@implementation FilamentView

+ (Class)layerClass {
#if FILAMENT_APP_USE_OPENGL
    return [CAEAGLLayer class];
#elif FILAMENT_APP_USE_METAL
    return [CAMetalLayer class];
#endif
}

- (instancetype)initWithCoder:(NSCoder*)coder {
    if (self = [super initWithCoder:coder]) {
#if FILAMENT_APP_USE_OPENGL
        [self initializeGLLayer];
#elif FILAMENT_APP_USE_METAL
        [self initializeMetalLayer];
#endif
        self.contentScaleFactor = UIScreen.mainScreen.nativeScale;
    }
    return self;
}

@end
3

Initialize the layer

Configure layer properties based on the backend:
- (void)initializeMetalLayer {
#if METAL_AVAILABLE
    CAMetalLayer* metalLayer = (CAMetalLayer*)self.layer;
    metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
    
    CGRect nativeBounds = [UIScreen mainScreen].nativeBounds;
    metalLayer.drawableSize = nativeBounds.size;
    metalLayer.opaque = YES;
#endif
}

Creating the SwapChain

Pass the layer to Filament when creating the SwapChain:
import Filament

class ViewController: UIViewController {
    var engine: Engine!
    var swapChain: SwapChain!
    var renderer: Renderer!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        guard let metalView = view as? FilamentView else {
            fatalError("View must be FilamentView")
        }
        
        // Create the engine
        engine = Engine.create()
        
        // Create SwapChain from Metal layer
        let layer = metalView.layer as! CAMetalLayer
        swapChain = engine.createSwapChain(layer)
        
        // Create renderer and other components
        renderer = engine.createRenderer()
        let scene = engine.createScene()
        let view = engine.createView()
        let camera = engine.createCamera(
            EntityManager.get().create()
        )
        
        view.camera = camera
        view.scene = scene
    }
}

Rendering Loop

Use CADisplayLink for the rendering loop:
class ViewController: UIViewController {
    var displayLink: CADisplayLink!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // ... setup code ...
        
        displayLink = CADisplayLink(
            target: self,
            selector: #selector(render)
        )
        displayLink.add(to: .main, forMode: .default)
    }
    
    @objc func render() {
        guard renderer.beginFrame(swapChain) else {
            return
        }
        
        renderer.render(view)
        renderer.endFrame()
    }
    
    deinit {
        displayLink.invalidate()
    }
}

Native C++ Integration

For maximum performance, use Filament’s C++ API directly:
ViewController.mm
#include <filament/Engine.h>
#include <filament/SwapChain.h>
#include <filament/Renderer.h>
#include <filament/View.h>

using namespace filament;

@implementation ViewController {
    Engine* _engine;
    SwapChain* _swapChain;
    Renderer* _renderer;
    View* _view;
    Scene* _scene;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    FilamentView* filamentView = (FilamentView*)self.view;
    
    _engine = Engine::create();
    
#if FILAMENT_APP_USE_METAL
    CAMetalLayer* layer = (CAMetalLayer*)filamentView.layer;
#else
    CAEAGLLayer* layer = (CAEAGLLayer*)filamentView.layer;
#endif
    
    _swapChain = _engine->createSwapChain((__bridge void*)layer);
    _renderer = _engine->createRenderer();
    _scene = _engine->createScene();
    _view = _engine->createView();
    
    _view->setScene(_scene);
}

- (void)render {
    if (_renderer->beginFrame(_swapChain)) {
        _renderer->render(_view);
        _renderer->endFrame();
    }
}

- (void)dealloc {
    _engine->destroy(_swapChain);
    _engine->destroy(_renderer);
    _engine->destroy(_view);
    _engine->destroy(_scene);
    Engine::destroy(&_engine);
}

@end

Handling Screen Resolution

Update the drawable size on rotation or resolution changes:
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    let metalView = view as! FilamentView
    let layer = metalView.layer as! CAMetalLayer
    
    // Update drawable size
    let scale = UIScreen.main.nativeScale
    let size = view.bounds.size
    layer.drawableSize = CGSize(
        width: size.width * scale,
        height: size.height * scale
    )
    
    // Update viewport
    let width = UInt32(size.width * scale)
    let height = UInt32(size.height * scale)
    view.viewport = Viewport(x: 0, y: 0, width: width, height: height)
}

Resource Management

Always clean up Filament resources:
deinit {
    displayLink?.invalidate()
    
    engine.destroySwapChain(swapChain)
    engine.destroyRenderer(renderer)
    engine.destroyView(view)
    engine.destroyScene(scene)
    engine.destroyCameraComponent(camera.entity)
    
    EntityManager.get().destroy(camera.entity)
    
    Engine.destroy(&engine)
}

Platform Capabilities

FeatureMetalOpenGL ES
iOS Version11.0+11.0+
PerformanceExcellentGood
Feature LevelUp to 3Up to 1
StatusRecommendedDeprecated

Next Steps

glTF Viewer

Use the high-level viewer API

ARKit Integration

Combine Filament with ARKit

Materials

Create custom materials

Performance

Optimize for mobile devices

Build docs developers (and LLMs) love