// the game engine

There is nothing
extra to install.

The engine is not a separate product layered on top of Zanna — it is the runtime every Zanna program already links against. Rendering, physics, audio, input, navigation, asset decoding and networking are all part of the standard library, and all of it was written for this project. No SDL, no PhysX, no FMOD, no stb.

// 3d rendering

Four backends, one API

Zanna.Graphics3D picks a GPU backend automatically and falls back to software. The choice is invisible to game code: the same calls produce a frame on all four.

PlatformPrimaryFallbackParity
macOSMetalSoftwareNear-full feature parity (94%)
WindowsDirect3D 11SoftwareFull feature parity
LinuxOpenGL 3.3SoftwareFull feature parity, including SSAO, depth of field and motion blur
AnywhereSoftware rasterizerAlways available; shadow maps, CSM with 3×3 PCF, normal and specular maps, per-pixel terrain splatting
A gameplay frame from the 3D Bowling demo: a lit bowling alley interior with textured lanes, pins, a scoreboard and an on-screen power meter
3D Bowling, rendered on Metal. Captured by the game’s own visual probe on a real build — the same code path that runs when you play it.

What the renderer does

  • Physically based materials: metallic/roughness, ambient occlusion, emissive, normal scale, alpha modes
  • Image-based lighting, clustered forward+, screen-space reflections
  • Cascaded shadow maps with PCF filtering, up to four directional slots
  • Soft particles, temporal anti-aliasing, reversed-Z depth, ACES tonemapping
  • SSAO, depth of field, motion blur, bloom, FXAA, vignette, colour grading
  • GPU skinning, morph targets, instancing, render-to-texture, cubemap skyboxes

The software path matters

The software rasterizer is not a stub. It is always available and produces the same image, which means 3D code runs everywhere — including headless machines and CI, where there is no GPU to fall back on.

It is also how the screenshots on this site could be produced deterministically: a scene is loaded, frames are rendered, and ScreenshotFinal() hands back pixels.

Triangle budget: the software renderer handles roughly 50K triangles at 30fps at 640×480. GPU backends handle 1M+ at 60fps.

// 2d

2D is software, deliberately

ZannaGFX rasterises 2D on the CPU and talks to the platform’s native windowing directly — Cocoa on macOS, native Wayland with an X11 fallback on Linux, Win32 GDI on Windows. There is no GPU dependency in the 2D path at all, which is what makes it identical everywhere.

Surfaces and drawing

  • Canvas and pixel buffers, blitting, alpha compositing, clipping
  • Vector paths, transforms and gradients
  • Bitmap and vector text from BDF and PSF font parsers
  • Sprites, atlases, tilemaps, particles, nine-slice panels
  • A deterministic mock backend so 2D rendering can be unit-tested

Formats, decoded from scratch

  • Images: BMP, PNG, JPEG and GIF decoders; BMP and PNG encoders
  • Audio: WAV, MP3 and OGG Vorbis
  • Models: OBJ, STL, FBX and glTF 2.0 / GLB
  • Compression: gzip, zstd, lz4
  • Every one of these is in-tree. That is what “zero dependencies” means in practice — the engine compiles on a clean machine with only a C compiler.

// simulation

Physics, navigation and animation

3D

  • Rigid bodies and colliders with a narrowphase, contact and solver split
  • Character controller with fixed-step movement
  • Distance, spring, hinge, rope and six-DOF joints
  • Raycast vehicle with suspension, drive and steering
  • Ragdolls and cloth
  • Convex hull generation via quickhull
  • Navmesh, nav agents and path queries

2D and animation

  • AABB and circle bodies, joints, collision layers, spatial queries
  • Quadtree broadphase, 2D raycasts, A* pathfinding
  • Skeletal animation with blend trees and animation controllers
  • IK solvers and morph targets
  • Node animation and animation players for scene graphs

// audio & input

Sound and controls

Audio

  • A 32-voice mixer with LRU voice eviction
  • Sounds, music, playlists and sound banks
  • Procedural synthesis and generated music
  • 3D spatial audio with listeners and positional sources
  • WAV, MP3 and OGG Vorbis decoded in-tree

Input

  • Keyboard, mouse, and up to four gamepads with rumble
  • Rebindable action maps rather than raw key checks
  • Key chords
  • Mouse capture and first-person camera handling

// scene pipeline

From an authored file to a running level

Scenes are data files, authored in Zanna Studio and loaded by the runtime. A scene never instantiates game classes by name — game code reads the document and maps typed metadata onto its own entities, so the format does not dictate how a game is structured.

FormatExtensionContents
2D scene document .scene2d Canonical JSON, schema v1: tile layers, placed-object hierarchy and draw order, typed scalar properties, asset references, diagnostics
3D scene .scene3d VSCN v1–v7: scene graph, materials with embedded texture maps, lights, cameras, typed node metadata (v6), prefab reference nodes (v7)

Getting content in

  • Tiled maps in JSON and TMX form for 2D
  • OBJ, STL, FBX and glTF/GLB for 3D, including cameras, lights and animation
  • An offline asset pipeline via zanna asset bake
  • ZPAK archives, either baked into the executable’s read-only data or shipped as a sidecar

Iterating

  • Run Scene launches the owning project with --scene <path>
  • Optional scene watching is a documented contract rather than an engine feature: a game that opts in re-runs its own scene-load path when the file changes, with no state migration
  • .scene, .level and .vscn remain accepted legacy extensions indefinitely

// what’s built with it

Games, not benchmarks

The engine is exercised by complete games in the repository rather than by isolated demos. They are how regressions get caught.

Ridgebound in daylight: an open landscape with terrain, a lake, procedural trees, a third-person character and a minimap
Ridgebound, midday.
The same Ridgebound scene at night, lit by moonlight with stars visible in the sky
The same scene, deep night.

One open-world scene at two world times, captured by the game’s own smoke probe. Nothing was moved between the two frames except the clock.

ashfall — first-person runtime
A first-person frame from Ashfall: a bolt pistol held at the lower right, mech silhouettes advancing through dust, and a health and ammo HUD.
The first-person stack. View-model rendering, point-light shadows and height fog exist because this game needed them. The weapon is drawn in its own depth range so it never clips into the world, and the HUD composites through the same overlay path a 2D game uses.

Scene-driven

  • Ashfall — a nine-mission 3D FPS campaign plus a hub, with every mission loaded from an authored .scene3d: ten weapons, eleven enemy archetypes and three bosses, navmesh routing, per-level skies and lighting
  • XENOSCAPE — a ten-region 2D Metroidvania whose regions load from .scene2d files
  • Both ship probes proving the authored scenes reproduce the old code-built levels byte for byte

Also in the tree

  • 3D: Ridgebound (open world), 3D Bowling, 3D Baseball
  • 2D: Chess with alpha-beta AI, Crackman, Centipede, Frogger, and a graphics showcase
  • BASIC: Tetris, Frogger, Pac-Man and Centipede, sharing the same runtime
  • Not games: ZannaSQL, a PostgreSQL-compatible database server and client; a paint app with layers and undo; a multi-threaded HTTP server

Worth knowing

  • Ship games as native builds. The bytecode VM is useful for bounded probes and tests, but it is not a real-time game execution target; interactive VM launches exit with the native build command rather than opening an unplayably slow window.
  • Backend parity is measured, not assumed. Metal sits at 94% of the feature set; Direct3D 11 validation depends on the Windows CI lane.
  • This is pre-alpha. Runtime APIs still change between versions, and there is no compatibility promise.