# What Graphics API Does ArmorPaint Use? A Deep Dive into Kinc's WebGPU Abstraction

> Discover ArmorPaint's graphics API strategy. Learn how Kinc's WebGPU abstraction enables dynamic targeting of Vulkan, Metal, D3D12, OpenGL, and WebGPU for cross-platform rendering.

- Repository: [Armory 3D/armorpaint](https://github.com/armory3d/armorpaint)
- Tags: deep-dive
- Published: 2026-09-13

---

**ArmorPaint does not use a single graphics API; instead, it leverages the Kinc engine's WebGPU abstraction layer to dynamically target Vulkan, Metal, Direct3D 12, OpenGL, or WebGPU depending on the platform.**

ArmorPaint, the open-source 3D texture painting software, relies on a sophisticated hardware abstraction layer rather than locking itself to one specific rendering backend. According to the armory3d/armorpaint source code, the application utilizes the **Kinc engine**'s WebGPU implementation to automatically select the optimal graphics API for each target platform. This architecture ensures maximum performance across Windows, macOS, Linux, Android, and Web browsers without requiring separate codebases for each graphics backend.

## ArmorPaint's Multi-Backend Graphics Architecture

Unlike applications hardcoded to OpenGL or DirectX, ArmorPaint employs a **WebGPU abstraction** that decouples the rendering logic from the underlying native API. The core header file [`base/sources/backends/webgpu.h`](https://github.com/armory3d/armorpaint/blob/main/base/sources/backends/webgpu.h) defines the `WGPUBackendType` enum, which enumerates every supported graphics backend the engine can initialize at runtime.

The supported backends include:

- **Vulkan** – Default for Windows and Linux desktops, providing high-performance GPU access
- **Metal** – Native backend for macOS, iOS, and iPadOS devices
- **Direct3D 12** – Fallback option on Windows when Vulkan is unavailable
- **OpenGL / OpenGL ES** – Legacy fallbacks for older Windows/Linux systems and Android devices
- **WebGPU** – Browser-native implementation for WebAssembly builds
- **Null / CPU** – Headless or software rendering for server environments

## How the WebGPU Abstraction Works

The abstraction layer centers on the `WGPUBackendType` enum defined in [`base/sources/backends/webgpu.h`](https://github.com/armory3d/armorpaint/blob/main/base/sources/backends/webgpu.h) (lines 114-124). This enum maps logical backend types to their native implementations:

```c
typedef enum WGPUBackendType {
    WGPUBackendType_Undefined = 0,
    WGPUBackendType_Null = 1,
    WGPUBackendType_WebGPU = 2,
    WGPUBackendType_D3D12 = 4,
    WGPUBackendType_Metal = 5,
    WGPUBackendType_Vulkan = 6,
    WGPUBackendType_OpenGL = 7,
    WGPUBackendType_OpenGLES = 8,
} WGPUBackendType;

```

The global GPU state structure `g_gpu`, declared in [`base/sources/iron_gpu.h`](https://github.com/armory3d/armorpaint/blob/main/base/sources/iron_gpu.h), stores the currently active backend type in its `backendType` member. This allows the engine to query which graphics API is driving the rendering pipeline at any point during execution.

## Platform-Specific Backend Selection

ArmorPaint's build system automatically selects the appropriate backend source files based on the compilation target. The Node.js build script [`base/project.js`](https://github.com/armory3d/armorpaint/blob/main/base/project.js) (lines 52-78) conditionally adds Vulkan, Metal, Direct3D 12, OpenGL, or WebGPU implementation files to the project depending on the target platform variables.

For example, when targeting Windows desktop, the build system prioritizes Vulkan sources but includes Direct3D 12 and OpenGL fallbacks. When targeting Apple platforms, it exclusively pulls the Metal backend sources. This selection happens at compile time, ensuring the binary only contains the necessary native graphics code for that specific platform.

## Working with Graphics Backends in Code

Developers interacting with ArmorPaint's source can manipulate the graphics backend through the WebGPU C API exposed in [`base/sources/backends/webgpu.h`](https://github.com/armory3d/armorpaint/blob/main/base/sources/backends/webgpu.h).

### Explicitly Selecting a Backend

To force a specific graphics API for debugging or testing purposes, initialize the `WGPUContext` structure with your desired backend before calling `wgpu_init`:

```c
#include "backends/webgpu.h"

void force_vulkan_backend(void) {
    WGPUContext ctx = {0};
    
    // Force Vulkan instead of letting Kinc auto-select
    ctx.backendType = WGPUBackendType_Vulkan;
    
    if (!wgpu_init(&ctx)) {
        // Handle initialization failure
        fprintf(stderr, "Failed to initialize Vulkan backend\n");
    }
}

```

### Querying the Active Backend at Runtime

You can determine which graphics API is currently driving the renderer by accessing the global `g_gpu` structure:

```c
#include "backends/webgpu.h"
#include "iron_gpu.h"
#include <stdio.h>

void print_graphics_api(void) {
    const char *backend_names[] = {
        "Undefined", "Null", "WebGPU", "D3D11", "D3D12",
        "Metal", "Vulkan", "OpenGL", "OpenGLES"
    };
    
    printf("Active graphics API: %s\n", 
           backend_names[g_gpu.backendType]);
}

```

### WebGPU in WebAssembly Builds

When ArmorPaint compiles to WebAssembly for browser deployment, the same [`webgpu.h`](https://github.com/armory3d/armorpaint/blob/main/webgpu.h) abstraction maps to the browser's native WebGPU JavaScript API:

```javascript
// Accessed through Kinc's WASM glue code
const canvas = document.getElementById('canvas');
const context = canvas.getContext('webgpu');

const device = await wgpu.requestDevice();
const swapChain = context.configureSwapChain({
    device: device,
    format: "bgra8unorm"
});

```

## Key Source Files for Graphics Implementation

Understanding the graphics API layer requires examining these critical files in the armory3d/armorpaint repository:

- **[`base/sources/backends/webgpu.h`](https://github.com/armory3d/armorpaint/blob/main/base/sources/backends/webgpu.h)** – Defines the `WGPUBackendType` enum and `WGPUContext` structure used for all graphics initialization
- **[`base/sources/iron_gpu.h`](https://github.com/armory3d/armorpaint/blob/main/base/sources/iron_gpu.h)** – Contains the global `g_gpu` state structure that tracks the active backend
- **[`base/project.js`](https://github.com/armory3d/armorpaint/blob/main/base/project.js)** – Build script that injects platform-specific backend sources (Vulkan, Metal, D3D12, etc.) during compilation
- **[`base/sources/backends/webgpu_gpu.c`](https://github.com/armory3d/armorpaint/blob/main/base/sources/backends/webgpu_gpu.c)** – Implementation file containing the platform-specific translation logic between WebGPU calls and native API commands

## Summary

- ArmorPaint uses **Kinc's WebGPU abstraction layer** rather than a single hardcoded graphics API
- The engine supports **Vulkan, Metal, Direct3D 12, OpenGL, OpenGL ES, and WebGPU** through the `WGPUBackendType` enum in [`base/sources/backends/webgpu.h`](https://github.com/armory3d/armorpaint/blob/main/base/sources/backends/webgpu.h)
- **Platform selection is automatic**, handled by the build system in [`base/project.js`](https://github.com/armory3d/armorpaint/blob/main/base/project.js) and runtime initialization in `wgpu_init()`
- Developers can **query or force specific backends** using the `g_gpu` global state and `WGPUContext` configuration
- The same codebase compiles to desktop (Windows/Linux/macOS), mobile (iOS/Android), and web targets without changing rendering logic

## Frequently Asked Questions

### Does ArmorPaint use Metal on macOS?

Yes. When compiled for macOS, iOS, or iPadOS, ArmorPaint automatically selects the **Metal** backend via `WGPUBackendType_Metal` as defined in [`base/sources/backends/webgpu.h`](https://github.com/armory3d/armorpaint/blob/main/base/sources/backends/webgpu.h). The build system excludes Vulkan and DirectX sources when targeting Apple platforms, ensuring native Metal performance on Apple silicon and Intel Macs.

### Can I force ArmorPaint to use OpenGL instead of Vulkan on Windows?

Yes, you can force a specific graphics API by modifying the `WGPUContext` initialization before `wgpu_init()` is called. Set `ctx.backendType = WGPUBackendType_OpenGL` to override the default Vulkan selection. However, this requires rebuilding from source, as the backend selection is compile-time optimized in [`base/project.js`](https://github.com/armory3d/armorpaint/blob/main/base/project.js).

### What graphics API does the web version of ArmorPaint use?

The WebAssembly build uses the **WebGPU** backend (`WGPUBackendType_WebGPU`), which maps to the browser's native WebGPU implementation. This is distinct from WebGL; ArmorPaint requires a browser with native WebGPU support (such as Chrome or Edge) to run in web mode, as it does not fall back to WebGL for web deployment.

### Is Vulkan the default graphics API on all desktop platforms?

Vulkan is the default on **Windows and Linux**, but not on **macOS**, where Metal is the only supported backend. On Windows, if Vulkan drivers are unavailable, ArmorPaint can fall back to Direct3D 12 or OpenGL, though this requires the appropriate backend sources to be included during the build process defined in [`base/project.js`](https://github.com/armory3d/armorpaint/blob/main/base/project.js).