3 unstable releases

Uses new Rust 2024

0.2.1 Jun 12, 2025
0.2.0 Jun 10, 2025
0.1.0 Nov 30, 2018

#264 in Game dev

Download history 3/week @ 2025-05-07 69/week @ 2025-06-04 206/week @ 2025-06-11 25/week @ 2025-06-18 5/week @ 2025-06-25 19/week @ 2025-07-09

54 downloads per month

MIT license

365KB
6K SLoC

🍁 Maple 🍁

A simple 3D Game Engine in Rust!

Features

3D Model Support: load and manipulate 3D GLTF models
Customizable: create your own Nodes and use predefined nodes for more specific functionality
Write Your Own Shaders: write your own shaders with GLSL
Easily Add UI's: using egui you can easily set up a UI

Example Images

Shadows Model Loading This work is based on "Japanese Restaurant Inakaya" by MGuegan, licensed under CC BY 4.0.

Guide to using the Engine

this guide goes over the basics of initializing the engine, adding nodes, and defining custom nodes.

you can find the code used in this tutorial here.

Initialization

lets start out by creating the bare minimum code to create and start the engine.

use maple::{Engine, config::{EngineConfig, Resolution}};
use std::{default::Default, error::Error};

fn main() -> Result<(), Box<dyn Error>> {
    let mut engine = Engine::init(EngineConfig {
        window_title: "Hello, Window!".to_string(),
        resolution: Resolution {
            width: 1920,
            height: 1080,
        },
        ..Default::default()
    })?;

    engine.begin()
}

if you run this code it creates a window at 1920x1080 resolution, but its a bit empty so next we'll create a scene.

Scene Creation

in this section we'll create the engine's scene. scenes can be defined then added to the engine to render that scene.

to keep it as organized, we should define the scene in a seperate file then import it into main.

use maple::context::scene::Scene;

pub struct MainScene;

impl MainScene {
    pub fn build() -> Scene {
        let mut scene = Scene::default();
        
        /* Scene will go here */

        scene
    }
}

this code creates a function that will build the scene when called

before we add Nodes to the scene lets load this scene into the engine

use maple::{Engine, config::{EngineConfig, Resolution}};
use std::{default::Default, error::Error};

// create and import the main scene module
pub mod main_scene;
use main_scene::MainScene;

fn main() -> Result<(), Box<dyn Error>> {
    let mut engine = Engine::init(EngineConfig {
        window_title: "Hello, Window!".to_string(),
        resolution: Resolution {
            width: 1920,
            height: 1080,
        },
        ..Default::default()
    })?;

    // load the scene into the engine
    engine.load_scene(MainScene::build());

    engine.begin()
}

Node Creation

now we can finally add nodes to the Scene!

Nodes are easiest to build with the NodeBuilder which is a struct that helps define nodes. we'll use this to create a model and camera.

Model

lets create a pyramid model.

use maple::context::scene::Scene;
use maple::nodes::{model::Primitive, Model, ModelBuilder, Builder, Buildable};

scene
    .add(
        "pyramid", // name
        Model::builder()
            .add_primitive(Primitive::Pyramid) // add a Pyramid mesh to the model node
            .build(), // builds the node
    );

Camera3D

thats great but the engine doesnt know where to render the pyramid from for that we need a camera. cameras define the perspective so we'll need to position it properly.

use maple::{
    math,
    nodes::{Buildable, Builder, Camera3D},
};

scene.add(
    "camera",
    Camera3D::builder()
        .position(math::vec3(0.0, 5.0, -10.0))
        .orientation_vector(math::vec3(0.0, -0.5, 1.0))
        .build(),
);

nning local AI models both on a Your scene file should now look like this:

use maple::{
    context::scene::Scene,
    math,
    nodes::{Buildable, Builder, Camera3D, Model, model::Primitive},
};

pub struct MainScene;

impl MainScene {
    pub fn build() -> Scene {
        let mut scene = Scene::default();

        scene.add(
            "camera",
            Camera3D::builder()
                .position(math::vec3(0.0, 5.0, -10.0))
                .orientation_vector(math::vec3(0.0, -0.5, 1.0))
                .build(),
        );

        scene.add(
            "pyramid",
            Model::builder().add_primitive(Primitive::Pyramid).build(),
        );

        scene
    }
}

Lighting

If everything has gone well then when you run the program you can see a window pop up and a pyramid in the center of the screen. However, the mesh is really dark since its just being lit by ambient light so now adding a light and some ground to the scene should help.

use maple::{
    context::scene::Scene,
    math,
    nodes::{Buildable, Builder, DirectionalLight, Model, model::Primitive},
};

scene.add(
    "light",
    DirectionalLight::builder()
        .direction(math::vec3(-1.0, 1.0, 0.0))
        .build(),
);

scene.add(
    "ground",
    Model::builder()
        .add_primitive(Primitive::Plane)
        .position(math::vec3(0.0, -2.0, 0.0))
        .scale_factor(10.0)
        .build(),
);

Contributing

Contributions are welcome! If you have suggestions for improvements, feel free to create a pull request or open an issue.

License

This project is licensed under the MIT License

Acknowledgments

Dependencies

~12–25MB
~403K SLoC