Library / SDK
AryanpurTech/BlueEngine avatar
AryanpurTech/BlueEngine

BlueEngine is a Rust graphics engine that swaps static and dynamic builds behind one feature flag

Blue Engine is a general-purpose and easy-to-use graphics engine written in rust.

529 stars28 forksRustApache-2.0

At a glance

What is it?
BlueEngine is a general-purpose Rust graphics engine that runs on Vulkan, D3D-12, GL-ES and Metal across Windows, Linux, macOS and mobile, and it publishes as four crates with the core crate itself built twice, statically and dynamically, selected by a Cargo feature. The README asks you to use the latest Rust version because the engine is always kept up to date.
Who is it for?
Adopt BlueEngine if you want a Rust graphics project that runs on the same code across desktop and mobile, because the engine runs across Vulkan, D3D-12, GL-ES and Metal and exposes the platforms through Cargo features rather than through separate builds. Do not adopt it for a project with a near-term deadline, since the README itself says the project is not dead but the development might seem slow sometimes, and the most recent tagged release is v0.10.0 from 2025-12-07.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 170 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The hello world shows the shape of the API

BlueEngine is described as a general-purpose, easy-to-use, extendable and portable graphics engine written in rust, and the README's opening code sample is worth reading line by line because it is the whole API surface a new user sees.

rust
use blue_engine::{
    prelude::{ Engine, ObjectSettings },
    primitive_shapes::triangle
};

fn main() -> Result<(), blue_engine::error::Error> {
    // initialize the engine
    let mut engine = Engine::new()?;

    // create a triangle
    triangle("my triangle", ObjectSettings::default(), &mut engine.renderer, &mut engine.objects)?;

    // run the engine
    engine
        .update_loop(move |_| {})?;

    Ok(())
}

Three things stand out. The result type is blue_engine::error::Error, so every fallible operation propagates with the question mark operator, and the error type is namespaced rather than being a generic Box. The engine is split into a renderer and an objects collection, and a primitive is created by handing it both plus a name and an ObjectSettings, which is how the object registry and the graphics pipeline stay separate.

And the shape creation is a free function rather than a method. The triangle comes from primitive_shapes, and it takes the renderer and the object registry as mutable borrows, which is a deliberate choice: the shape constructor needs to register GPU resources in one and add an object to the other, and doing that as a free function keeps the constructor out of the type's method namespace and makes it obvious from the call site which of the two subsystems is being touched.

The prelude module is where Engine and ObjectSettings come from, so a user only imports the prelude rather than the module tree.

The final call is update_loop with a closure, which is the frame loop. The closure takes an argument and the engine is moved into it, so the borrow of the engine ends before the loop starts.

The whole sample fits on a screen, and the README points to an examples/ directory for a sense of how things are done, along with a separate utilities library on crates.io for extra functionality.

One engine, four graphics APIs, and how the abstraction is chosen

The About section makes the platform claim in one sentence. The engine can run on many popular back-end APIs including Vulkan, D3D-12, GL-ES and Metal as well as Windows, Linux, Mobile and OSX to ensure cross-platform compatibility.

Four graphics APIs is the meaningful number. Vulkan and Metal are the modern native paths, D3D-12 is what a Windows game needs, and GL-ES is the fallback for mobile and for hardware where the newer APIs are not available. Covering those four is what makes a single codebase runnable on a workstation, a laptop and a phone.

The Cargo.toml shows that the abstraction is a dependency rather than something written in the repository. The package depends on blue_engine_core and, optionally, blue_engine_dynamic, with the feature list wiring each flag to both crates in parallel: window enables the window feature on core and on dynamic, debug does the same, headless does the same, android and the two android activity variants do the same, and u32 and glam_fast_math likewise.

That pairing is the design. Rather than having one crate with a single implementation, the project publishes the core twice, once as a static build and once as a dynamic build, and the feature flags propagate to whichever is active.

Two of those flags are mutually exclusive by construction and the Cargo.toml comments say so. The window feature enables a window for rendering and this needs the headless feature to be disabled. The headless feature enables rendering in headless mode, and without a window, and that also needs the window feature to be disabled. The android feature is for android builds and also needs the headless feature disabled, and the two android activity variants, android_native_activity and android_game_activity, split the difference between the two kinds of Android activity an app can have.

The remaining two are ordinary performance switches. u32 means using u32 for indices and others, and glam_fast_math turns on the fast math variant of the glam maths library, which is the trade of exactness for speed in the matrix and vector operations that a renderer does constantly.

The default feature set is debug, window and static_link, which is the combination that gives you a working windowed application on a desktop in debug mode with the statically linked core.

The examples directory, the utilities crate and the cross-platform build badge

Three things in the repository point at how the engine is meant to be used in practice.

The examples/ directory is described in the README as the place to check out to get a sense of how things are done, and the top-level entries give its shape. There is a README.md, a Dockerfile, and then directories for camera/, resources/, shapes/ and utils/. The separation mirrors the engine's own structure: shapes/ is where the primitive and geometry examples live, camera/ is where the viewpoint and projection work is shown, resources/ holds the assets the examples load, and utils/ holds shared helper code the examples import.

The Dockerfile inside examples/ is a detail worth pausing on. An engine that runs on Windows, Linux, macOS and mobile is not straightforward to ship as a native binary, and a container is the usual way to produce a reproducible build of a desktop application, so the presence of a Dockerfile in the examples directory rather than at the repository root suggests the examples are the part meant to be run in a container.

The second pointer is the utilities library. The README links a separate crate, blue_engine_utilities, for extra functionality with the engine, and the Cargo.toml at the root confirms it is a separate published crate rather than a module inside the main one. A separate crate for utilities means a user can pull in the extras without them becoming a hard dependency of the engine itself, and it is also the one the justfile publishes last.

The third is the build badge. The single workflow badge at the top of the README is called Cross Platform Build and points at a release.yml workflow, which is a cross-platform build rather than a plain test run. There is also a docs.rs badge for blue_engine, and the documentation link in the README is marked as work in progress with a WIP tag next to the Guide.

The rest of the top-level entries are the ordinary parts of a Rust project: a Cargo.toml and a Cargo.lock, a CHANGELOG.md generated by git-cliff, a cliff.toml configuring it, a justfile with the release recipes, an examples/ directory, a crates/ directory holding the sub-crates, a src/ directory for the root crate, and the usual .github/, .gitignore, CODE_OF_CONDUCT.md, CONTRIBUTING.md and LICENSE.txt.

The Cargo.toml's own metadata is worth one more look, because it states the intent more precisely than the README does. The description is General-Purpose, Easy-to-use, Fast, and Portable graphics engine, the keywords are gamedev, graphics, 3D, 2D and rendering, and the categories are game-development, gui, graphics and rendering. The edition is 2024, which is the newest Rust edition, and the author is Elham Aryanpur.

Four crates, a changelog generated by git-cliff, and a slow-release warning

The publishing arrangement is in the justfile, and it explains the crate layout that the Cargo.toml depends on.

text
publish:
    @cd crates/blue_engine_core && cargo publish --allow-dirty
    @cd crates/blue_engine_dynamic && cargo publish --allow-dirty
    @cargo publish --allow-dirty
    @cd crates/blue_engine_utilities && cargo publish --allow-dirty

Four crates are published in a specific order: the core, then the dynamic build of it, then the root crate itself, then the utilities library. The core has to exist on the registry before the root crate can depend on it, and the root crate before the utilities crate can depend on it, so the sequence is a dependency order rather than a preference. The --allow-dirty flag on each is what lets the release be run from a working tree that has uncommitted changes, which is a convenience rather than a virtue.

The changelog is generated too, by a separate recipe:

text
update-changelog release_tag:
    git cliff --unreleased --tag {{release_tag}} --prepend CHANGELOG.md

git-cliff generates the changelog from the conventional commit history, and the repository has a cliff.toml at the root configuring it. So the CHANGELOG.md at the root is a build artefact of the commit log rather than something written by hand, and the recipe prepends the new section when a tag is cut.

The release history shows how often that happens. v0.10.0, refactors and dependency update, from 2025-12-07. v0.9.4, translation direction fix, from 2025-08-06. v0.9.3, input and object position fix, from 2025-08-05.

Two of those three release names are bug fixes on rendering behaviour, translation direction and object position, and both landed within a day of each other in August 2025. That tells you something about the state of the engine: the object model and the coordinate handling were still settling.

The README also carries a line that is worth reading as a status note rather than as a boast: the project isn't dead, just the development might seem slow sometimes. Combined with a last release in December 2025 and a last push on 2026-05-06, the honest reading is that the engine is maintained in bursts rather than continuously. The top-level CHANGELOG.md, CODE_OF_CONDUCT.md, CONTRIBUTING.md and LICENSE.txt are all present, so the project is set up properly even where the cadence is uneven.

Where BlueEngine is the wrong tool

Three limits, and the first is about the licence of the underlying abstraction.

The first is that the engine sits on a graphics abstraction, and that abstraction has its own licence and its own platform support matrix. The Cargo.toml shows the dependency is not optional and not vendored, so the set of back-end APIs you can actually use on a given machine is the intersection of what BlueEngine supports and what the abstraction supports on that machine. Vulkan, D3D-12, GL-ES and Metal covers the mainstream cases, but on a Linux box with an old driver, or on a device with an unusual GPU, the GL-ES path is what you get, and the performance characteristics of that path are not the ones the D3D-12 or Metal numbers would suggest.

The second is the release cadence and what it implies for a project with a deadline. The most recent tagged release is v0.10.0 from 2025-12-07 and the two before it were rendering fixes from August 2025. The README's own note that development might seem slow sometimes is the author being straight about it. If you need a maintained engine with a predictable release train and a responsive maintainer, this is not it, and the honest comparison is that the Rust graphics ecosystem moves faster elsewhere.

The third is the feature-flag combinatorial surface. To get a build that actually does what you want, you are choosing between static and dynamic linking, between windowed and headless, and between debug and release, with the constraint that window and headless exclude each other and that android excludes headless. The Cargo.toml comments are explicit about those exclusions, which is helpful, but it does mean the feature matrix is something you have to reason about rather than switch on one flag. And the two android activity variants suggest the Android integration has two entry shapes to choose between.

The alternative approach for most people is to write against the graphics abstraction directly. You get the API portability with none of the engine's object model, and you keep the abstraction's own release cadence instead of depending on an engine that releases in bursts. The difference in approach is that BlueEngine gives you a scene graph, an object registry, a primitive library and a frame loop that work together, so a first triangle is fifteen lines rather than a hundred, while using the abstraction alone means you build the renderer loop yourself and keep the parts the engine would have smoothed over.

For a learning project or a prototype, that trade is obviously worth it. For a shipped game, the burst cadence and the feature matrix are the two things to test before committing.

Editorial conclusion

Adopt BlueEngine if you want a Rust graphics project that runs on the same code across desktop and mobile, because the engine runs across Vulkan, D3D-12, GL-ES and Metal and exposes the platforms through Cargo features rather than through separate builds. Do not adopt it for a project with a near-term deadline, since the README itself says the project is not dead but the development might seem slow sometimes, and the most recent tagged release is v0.10.0 from 2025-12-07. Verify first that you are on a recent Rust toolchain, since the README asks for the latest Rust version, that the feature combination you choose makes sense for your target, since window and headless are mutually exclusive and android also excludes headless, and that you understand the static or dynamic choice, since static_link and dynamic_link pick between two builds of the same core crate.

Frequently asked questions

What is BlueEngine?

It is a general-purpose, easy-to-use, extendable and portable graphics engine written in Rust, published on crates.io as blue_engine. The engine can run on Vulkan, D3D-12, GL-ES and Metal across Windows, Linux, mobile and macOS.

What does the BlueEngine hello world look like?

You create an Engine with Engine::new(), call a primitive shape function such as triangle with a name and ObjectSettings plus the renderer and object registry, then run engine.update_loop with a closure. The result type is blue_engine::error::Error, and the imports come from the prelude module.

What is the difference between static_link and dynamic_link in BlueEngine?

The engine's core is published twice, as blue_engine_core for the static build and blue_engine_dynamic for the dynamic build, and the Cargo features select between them. The default feature set is debug, window and static_link.

Which BlueEngine Cargo features are mutually exclusive?

The window feature enables a window for rendering and needs the headless feature to be disabled, and the headless feature enables rendering without a window and also needs window to be disabled. The android feature for Android builds likewise needs headless disabled.

How is the BlueEngine changelog generated?

With git-cliff. The justfile has an update-changelog recipe that runs git cliff with the unreleased flag and the release tag and prepends the result to CHANGELOG.md, with the configuration in cliff.toml at the repository root.

Which crates does BlueEngine publish?

Four, in dependency order: blue_engine_core, blue_engine_dynamic, the root blue_engine crate, and blue_engine_utilities. The justfile publish recipe cargo publishes each of them in that order, and the utilities library is also available separately on crates.io.

Official sources

  1. AryanpurTech/BlueEngine on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/aryanpurtech-blueengine.svg)](https://hysenlabs.com/projects/aryanpurtech-blueengine)

Was this useful?