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

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, 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, 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. 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 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 provides string mapping for UI display.

  3. Fast3D initialization — src/port/UI/LighthouseMenu.cpp (lines 163-171) reads the selected enum and passes it to Fast3D's initialization routine:

// 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.

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 before launch:

{
    "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:

// 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 Defines WindowBackend enum and string mappings
src/port/UI/LighthouseMenu.cpp Reads configuration and forwards selection to Fast3D
README.md Documents backend IDs and platform defaults
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 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 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 (lines 163-171), and the selected API remains active for the session. A restart is required to reinitialize with a different backend.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →