nightshade 0.53.0

A cross-platform data-oriented game engine.
Documentation

Nightshade

A data-oriented 3D game engine written in Rust. Targets native (Windows, macOS, Linux) and the web via WebGPU. Ships a glTF-first PBR renderer with the full KHR extension set, a freecs-backed ECS, a retained-mode UI, and a browser-playable scene editor.

See the project README for screenshots, the live demo, and the project status.

Getting Started

Use the nightshade-template to scaffold a new project, or add nightshade to your Cargo.toml:

[dependencies]

nightshade = "0.53.0"

Hello, Nightshade

use nightshade::prelude::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugin(SpinCubePlugin)
        .run()
}

#[derive(Default)]
struct SpinCube {
    cube: Option<Entity>,
    time: f32,
}

struct SpinCubePlugin;

impl Plugin for SpinCubePlugin {
    fn build(&self, app: &mut App) {
        app.insert_resource(SpinCube::default());
        app.add_system(Stage::Startup, initialize);
        app.add_system(Stage::Update, spin);
    }
}

fn initialize(game: &mut SpinCube, world: &mut World) {
    world.resources.render_settings.atmosphere = Atmosphere::Nebula;
    let camera = spawn_pan_orbit_camera(
        world,
        Vec3::zeros(), 5.0, 0.5, 0.3,
        "Camera".to_string(),
    );
    world.resources.active_camera = Some(camera);
    spawn_sun(world);
    game.cube = Some(spawn_mesh_at(world, "Cube", Vec3::zeros(), Vec3::new(1.0, 1.0, 1.0)));
}

fn spin(game: &mut SpinCube, world: &mut World) {
    pan_orbit_camera_system(world);
    game.time += world.resources.window.timing.delta_time;
    if let Some(entity) = game.cube
        && let Some(transform) = world.get_mut::<LocalTransform>(entity)
    {
        transform.rotation = nalgebra_glm::quat_angle_axis(game.time, &Vec3::y_axis());
    }
}

Architecture

The engine sits on top of a standalone renderer:

  • nightshade owns the ECS, the frame schedule, physics, animation, audio, input, UI, asset loading, and the render driver that snapshots the scene into the renderer's per-frame inputs.
  • nightshade-renderer is a standalone GPU-driven wgpu renderer. It consumes one owned RenderInputs value per frame and never sees the ECS world. Its frame graph (pass scheduling, transient resource aliasing, store-op optimization) is usable on its own through the rendergraph feature.

Each layer only knows the one below it.

Features

default = ["engine", "wgpu"]. Opt in to more with cargo run --features <name>.

Feature What it adds
engine Default. Runtime + asset loading + scene graph + picking + file dialogs + screenshot
wgpu Default. GPU rendering (DX12 / Metal / Vulkan / WebGPU)
full engine + wgpu + audio + physics + gamepad + navmesh + shell
audio Audio playback (kira)
physics 3D physics (rapier3d)
gamepad Controller input (gilrs)
navmesh Runtime navmesh queries
navmesh-bake Navmesh baking (rerecast)
shell In-game shell commands
gizmos Translate / rotate / scale gizmos
debug_render Line / shape debug overlays
file_watcher Live asset reload (notify)
screenshot Capture viewport to PNG
steam Steam integration (steamworks)
tracing tracing-subscriber logging
tracy Tracy profiler integration
chrome chrome-trace profiler output
windows-app-icon Embed app icon on Windows

Browser Support

WebGPU is supported in:

  • All chromium-based browsers (Chrome, Edge, Brave, Vivaldi, etc.)
  • Firefox 141+
  • Safari Technology Preview 18+

License

Dual-licensed under either of:

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in nightshade by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.