Introduction
View the Gallery - Live demos of Nightshade's features running in your browser.
Nightshade is a 3D game engine written in Rust. It handles rendering, physics, audio, animation, input, and windowing, and exposes them through a single trait the game implements. The engine is the kernel that runs every frame. The game is the data and the per-frame logic that runs alongside it.
The runtime is built from four libraries. wgpu handles cross-platform GPU access, targeting Vulkan, Metal, DirectX 12, and WebGPU from a single API. Rapier3D runs the physics at a fixed timestep with interpolation for smooth rendering. Kira drives audio playback and spatial sound. glTF is the model format, with skeletal animation, materials, and scene hierarchy loaded out of the box. The rest of the engine is the glue that ties those pieces to an entity component system and a frame schedule.
How a Nightshade application is shaped
A game implements the State trait. Three methods carry most of the load. initialize runs once at startup and sets up the scene, the camera, the lights, and any entities the game needs. run_systems runs every frame and is where game logic lives. Input handlers like on_keyboard_input fire when events arrive.
The engine owns the World. The World holds every entity, every component, and a Resources struct of singletons grouped by domain (physics, input, assets, text, loading, transform_state, cleanup, entities, commands, schedules). Game code reads and writes the World to drive what happens on screen.
┌─────────────────────────────────────────────────────────────┐
│ Your Game (State) │
├─────────────────────────────────────────────────────────────┤
│ initialize() │ run_systems() │ ui() │ input handlers │
└────────────────┴─────────────────┴────────┴─────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ World │
├──────────────────┬──────────────────┬───────────────────────┤
│ Entities │ Components │ Resources │
│ (unique IDs) │ (data arrays) │ (global singletons) │
└──────────────────┴──────────────────┴───────────────────────┘
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Renderer │ │ Physics │ │ Audio │
│ (wgpu) │ │ (Rapier) │ │ (Kira) │
└───────────────┘ └───────────────┘ └───────────────┘
The frame loop
Each frame proceeds in a fixed order. The engine processes window and input events from winit. It calls run_systems on the game state. The frame schedule runs the engine systems (physics step, animation sampling, transform propagation, text sync, cleanup). The render graph executes its passes against the resulting ECS state and submits the command buffer. The swapchain presents.
The game owns the contents of run_systems. Everything else happens automatically. The schedule itself is data, stored at world.resources.schedules.frame, so a game can insert, remove, or reorder engine systems from initialize when it needs to.
What the engine ships with
Rendering is PBR with a metallic-roughness workflow. Directional, point, and spot lights with shadow maps. Post-processing covers SSAO, SSGI, SSR, bloom, depth of field, and tonemapping. Skeletal animation samples bone transforms straight into the ECS, where the renderer reads them. There is a particle system, a procedural terrain pass, and a grass pass that draws thousands of blades.
Physics covers rigid bodies, character controllers, and the usual collider shapes (box, sphere, capsule, cylinder, convex hull, trimesh, heightfield). Joints cover fixed, revolute, prismatic, spherical, rope, and spring. Raycasting is the primary query.
Audio plays WAV, OGG, MP3, and FLAC, with 3D positioned sources and distance attenuation. Input covers keyboard, mouse, and gamepad (analog sticks, triggers, rumble), with cursor locking for first-person games. Pathfinding goes through a Recast navigation mesh. Debug rendering, HUD text, screenshot capture, and an in-game developer console are part of the standard kit. Steam integration sits behind a feature flag.
The same code runs on Windows, macOS, Linux, and WebAssembly. The graphics backend is picked at runtime.
What this book covers
The next chapters walk through installation, the first application, the project layout, and the architecture in detail. The runnable demo at the end of this section is a single-file Rust program that builds for the browser through WebAssembly and renders the same scene you see in the gallery.
The reference for engine code lives at docs/USAGE.md inside the repository. The API docs are at docs.rs/nightshade. The source is at github.com/matthewjberger/nightshade.