# How DirectX 11, OpenGL, and Metal Backends Are Implemented in Lighthouse

> Discover how Lighthouse implements DirectX 11 OpenGL and Metal rendering backends using Fast3D for a seamless user experience across Windows macOS and other platforms.

- Repository: [Harbour Masters/Lighthouse](https://github.com/HarbourMasters/Lighthouse)
- Tags: internals
- Published: 2026-08-04

---

**Lighthouse delegates all rendering to the Fast3D library and selects the appropriate backend through a single `WindowBackend` enum defined in [`src/port/UI/MenuTypes.h`](https://github.com/HarbourMasters/Lighthouse/blob/main/src/port/UI/MenuTypes.h), with DirectX 11 for Windows, OpenGL for cross-platform use, and Metal for macOS.**

Every rendering path in the HarbourMasters/Lighthouse project—whether DirectX 11, OpenGL, or Metal—flows through the same abstraction layer. The engine itself does not contain platform-specific graphics code. Instead, Lighthouse configures which **Fast3D** backend to initialize, then lets the submodule handle API-specific initialization and command submission. This design keeps the main codebase clean while supporting three distinct rendering APIs across Windows, Linux, and macOS.

## Backend Selection Through MenuTypes.h

The core abstraction lives in **[`src/port/UI/MenuTypes.h`](https://github.com/HarbourMasters/Lighthouse/blob/main/src/port/UI/MenuTypes.h)**, where the `WindowBackend` enum maps integers to rendering implementations:

| Backend ID | Enum Value | Rendering API | Platform |
|------------|-----------|---------------|----------|
| 1 | `FAST3D_DXGI_DX11` | DirectX 11 (DXGI + D3D11) | Windows |
| 2 | `FAST3D_SDL_OPENGL` | OpenGL (via SDL2) | All platforms |
| 3 | `FAST3D_SDL_METAL` | Metal (via SDL2) | macOS |

The enum values appear at lines 274-276 in [`MenuTypes.h`](https://github.com/HarbourMasters/Lighthouse/blob/main/MenuTypes.h). These constants are the only anchor points Lighthouse needs to distinguish rendering paths.

## How the Backend Is Activated

The selection flow spans three components:

1. **User configuration** — Edit [`lighthouse.cfg.json`](https://github.com/HarbourMasters/Lighthouse/blob/main/lighthouse.cfg.json) or use the Settings menu. The `"Backend"` entry accepts IDs 1, 2, or 3. The README at lines 70-73 documents these values and platform defaults.

2. **Enum translation** — [`MenuTypes.h`](https://github.com/HarbourMasters/Lighthouse/blob/main/MenuTypes.h) provides string mapping for UI display.

3. **Fast3D initialization** — **[`src/port/UI/LighthouseMenu.cpp`](https://github.com/HarbourMasters/Lighthouse/blob/main/src/port/UI/LighthouseMenu.cpp)** (lines 163-171) reads the selected enum and passes it to Fast3D's initialization routine:

```cpp
// From LighthouseMenu.cpp - backend selection forwarded to Fast3D
Fast::WindowBackend selectedBackend = static_cast<Fast::WindowBackend>(configBackendId);
renderer.initialize(selectedBackend);

```

Lighthouse never touches DXGI, OpenGL contexts, or Metal command queues directly.

## DirectX 11 Backend Implementation

The **DirectX 11** path uses **DXGI** for swap-chain management and **Direct3D 11** for rendering.

- **Initialization**: Fast3D creates a DXGI swap chain, instantiates a D3D11 device and immediate context, and binds the render target view.
- **Platform constraint**: Windows-only. The CMake build system conditionally includes DirectX-specific source files when targeting Windows.

This backend offers the tightest display integration on Windows and is typically the default for that platform.

## OpenGL Backend Implementation

The **OpenGL** backend provides the broadest platform coverage.

- **API layer**: OpenGL 3.x/4.x via SDL2 windowing.
- **Initialization sequence**: 
  1. SDL creates an OpenGL-compatible window using `SDL_WINDOW_OPENGL`
  2. Fast3D obtains an OpenGL context
  3. Function pointers are loaded (e.g., via `glad`)
  4. Framebuffer configuration completes the setup

- **CMake dependency**: The build requires `find_package(OpenGL REQUIRED)` as shown at lines 182-183 of [`CMakeLists.txt`](https://github.com/HarbourMasters/Lighthouse/blob/main/CMakeLists.txt).

This backend works on Windows, Linux, and macOS, making it the fallback and development standard.

## Metal Backend Implementation

The **Metal** backend targets Apple's modern graphics API.

- **API layer**: Metal through SDL2's Metal window support.
- **Initialization sequence**:
  1. SDL window created with `SDL_WINDOW_METAL` flag
  2. Fast3D extracts the `CAMetalLayer` from the window
  3. Metal device and command queue are instantiated
  4. Rendering proceeds through Metal command buffers

- **Platform constraint**: macOS-only. The README notes Metal as the default on Apple platforms.

Metal provides lower overhead and better performance on modern Mac hardware compared to the OpenGL fallback.

## Practical Backend Configuration

To switch backends, modify [`lighthouse.cfg.json`](https://github.com/HarbourMasters/Lighthouse/blob/main/lighthouse.cfg.json) before launch:

```json
{
    "Backend": {
        "id": 2,
        "Name": "OpenGL"
    }
}

```

Valid `id` values: **1** for DirectX 11, **2** for OpenGL, **3** for Metal. The change requires an application restart—no runtime backend switching is implemented.

Programmatically, the selection appears as:

```cpp
// Illustrative: direct enum usage
Fast::WindowBackend backend = Fast::WindowBackend::FAST3D_SDL_OPENGL;
Fast::Renderer renderer;
renderer.initialize(backend);  // Fast3D handles all API-specific setup

```

## Key Source Files

| File | Purpose |
|------|---------|
| [`src/port/UI/MenuTypes.h`](https://github.com/HarbourMasters/Lighthouse/blob/main/src/port/UI/MenuTypes.h) | Defines `WindowBackend` enum and string mappings |
| [`src/port/UI/LighthouseMenu.cpp`](https://github.com/HarbourMasters/Lighthouse/blob/main/src/port/UI/LighthouseMenu.cpp) | Reads configuration and forwards selection to Fast3D |
| [`README.md`](https://github.com/HarbourMasters/Lighthouse/blob/main/README.md) | Documents backend IDs and platform defaults |
| [`CMakeLists.txt`](https://github.com/HarbourMasters/Lighthouse/blob/main/CMakeLists.txt) | Declares OpenGL package dependency |

## Summary

- Lighthouse implements **no rendering code directly**—all graphics operations delegate to the Fast3D submodule.
- **Three enum values** in [`MenuTypes.h`](https://github.com/HarbourMasters/Lighthouse/blob/main/MenuTypes.h) differentiate DirectX 11, OpenGL, and Metal backends.
- **Platform availability** is enforced through CMake conditionals and SDL2 window flags, not runtime detection.
- **Configuration** happens through JSON or the Settings menu, with Fast3D handling all API-specific initialization.
- **OpenGL** provides cross-platform compatibility; **DirectX 11** optimizes for Windows; **Metal** targets modern macOS.

## Frequently Asked Questions

### How do I switch between DirectX 11, OpenGL, and Metal in Lighthouse?

Edit the [`lighthouse.cfg.json`](https://github.com/HarbourMasters/Lighthouse/blob/main/lighthouse.cfg.json) file in your installation directory. Set `"Backend"` → `"id"` to **1** for DirectX 11, **2** for OpenGL, or **3** for Metal. Alternatively, use the in-game Settings menu if available. The change takes effect after restarting the application.

### Why doesn't Lighthouse implement its own rendering code?

The project follows a **backend delegation pattern** to minimize platform-specific code in the main repository. By relying on Fast3D---a dedicated graphics abstraction library---Lighthouse maintains cleaner architecture and easier cross-platform maintenance. Only configuration and enum selection live in the main codebase.

### Which backend should I use on each platform?

Use **DirectX 11** (ID 1) on Windows for optimal display integration. Choose **Metal** (ID 3) on macOS for best performance on Apple Silicon and modern Intel Macs. Select **OpenGL** (ID 2) on Linux, or as a compatibility fallback on any platform when the native backend encounters issues.

### Can I switch backends without restarting Lighthouse?

No---backend initialization occurs during application startup when Fast3D creates the graphics context, swap chain, and device. The `WindowBackend` enum is passed to `renderer.initialize()` early in [`LighthouseMenu.cpp`](https://github.com/HarbourMasters/Lighthouse/blob/main/LighthouseMenu.cpp) (lines 163-171), and the selected API remains active for the session. A restart is required to reinitialize with a different backend.