charge

Crates.iocharge
lib.rscharge
version0.1.1
created_at2025-12-09 06:18:09.988555+00
updated_at2025-12-09 06:18:09.988555+00
descriptionModern, minimal, efficient Vulkan game engine
homepage
repositoryhttps://github.com/example/charge
max_upload_size
id1974921
size177,893
saptak santra (saptak7777)

documentation

README

CHARGE

[!WARNING] Beta Release (v0.1.1): This version is an early release and is not fully optimized. Full optimization and missing features will be available in v0.1.8, which is scheduled for release within one month.

Modern, Minimal, Efficient Vulkan Game Engine

Rust License Vulkan


โœจ Features

  • ๐ŸŽฎ PBR Rendering โ€“ Physically-based materials with metallic-roughness workflow
  • ๐ŸŒ‘ Shadow Mapping โ€“ Real-time directional shadows with PCF soft filtering
  • ๐Ÿ–ผ๏ธ Bindless Textures โ€“ Efficient GPU texture management via descriptor indexing
  • ๐Ÿ”ฅ Post-Processing โ€“ HDR tonemapping (ACES) and bloom effects
  • โšก Compute Shaders โ€“ GPU compute infrastructure for advanced effects
  • ๐Ÿงฉ ECS Integration โ€“ Built-in Entity Component System using archetype_ecs
  • ๐Ÿ“ฆ glTF/GLB Loading โ€“ Native support for industry-standard 3D models

๐Ÿš€ Quick Start

Prerequisites

  • Rust 1.70+
  • Vulkan SDK (with glslc in PATH for shader compilation)
  • Windows, Linux, or macOS

Installation

Add to your Cargo.toml:

[dependencies]
charge = { path = "path/to/charge" }
winit = "0.30"

Minimal Example

use charge::{Renderer, ChargeApp};
use winit::{
    application::ApplicationHandler,
    event::WindowEvent,
    event_loop::{ActiveEventLoop, ControlFlow, EventLoop},
    window::{Window, WindowId},
};

struct App {
    window: Option<Window>,
    renderer: Option<Renderer>,
}

impl ApplicationHandler for App {
    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
        let window = event_loop
            .create_window(Default::default())
            .expect("Failed to create window");
        
        let renderer = Renderer::new(&window)
            .expect("Failed to create renderer");
        
        self.window = Some(window);
        self.renderer = Some(renderer);
    }

    fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
        match event {
            WindowEvent::CloseRequested => event_loop.exit(),
            WindowEvent::RedrawRequested => {
                if let Some(renderer) = &mut self.renderer {
                    let _ = renderer.render_frame();
                }
            }
            _ => {}
        }
    }

    fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
        if let Some(window) = &self.window {
            window.request_redraw();
        }
    }
}

fn main() {
    let event_loop = EventLoop::new().unwrap();
    event_loop.set_control_flow(ControlFlow::Poll);
    
    let mut app = App { window: None, renderer: None };
    let _ = event_loop.run_app(&mut app);
}

๐Ÿ“– API Usage

Using ChargeApp (Recommended)

ChargeApp is a high-level wrapper that combines the renderer with an ECS world:

use charge::ChargeApp;
use charge::renderer::mesh::{MeshDescriptor, MaterialDescriptor};
use charge::renderer::Mesh;
use charge::ecs::components::Material;

// Create app
let mut app = ChargeApp::new(&window)?;

// Load a mesh from GLB
let mesh = Mesh::from_gltf("assets/model.glb")?;

// Create descriptors
let mesh_descriptor = MeshDescriptor {
    key: mesh.name.clone(),
    vertices: mesh.vertices.clone(),
    indices: mesh.indices.clone(),
    texture: mesh.texture_data.clone(),
    normal_texture: mesh.normal_texture_data.clone(),
    metallic_roughness_texture: mesh.metallic_roughness_texture_data.clone(),
    occlusion_texture: mesh.occlusion_texture_data.clone(),
    emissive_texture: mesh.emissive_texture_data.clone(),
    material_properties: mesh.material_properties().cloned(),
};

let material_descriptor = MaterialDescriptor {
    material: Material::default(),
};

// Register mesh with ECS (spawns entity automatically)
let (entity_id, mesh_handle, material_handle, key) = 
    app.register_mesh_entity(&mesh_descriptor, &material_descriptor, None)?;

// Game loop
loop {
    app.update();          // Tick ECS systems
    app.render()?;         // Render frame
}

Using Renderer Directly

For lower-level control without ECS:

use charge::Renderer;
use charge::renderer::Mesh;

let mut renderer = Renderer::new(&window)?;

// Load and set mesh
let mesh = Mesh::from_gltf("assets/model.glb")?;
renderer.set_mesh(mesh);

// Configure camera
let camera = renderer.camera_mut();
camera.position = glam::Vec3::new(0.0, 2.0, 5.0);
camera.target = glam::Vec3::ZERO;

// Render loop
loop {
    renderer.render_frame()?;
}

Camera Control

// Position the camera
let camera = renderer.camera_mut();
camera.position = glam::Vec3::new(0.0, 5.0, 10.0);
camera.target = glam::Vec3::new(0.0, 0.0, 0.0);
camera.up = glam::Vec3::Y;
camera.fov = 60.0_f32.to_radians();
camera.near = 0.1;
camera.far = 1000.0;

Transform Control

// Rotate and scale the mesh
let transform = renderer.transform_mut();
transform.set_position(glam::Vec3::new(0.0, 1.0, 0.0));
transform.set_rotation(glam::Vec3::new(0.0, 1.57, 0.0)); // radians
transform.set_scale(glam::Vec3::splat(2.0));

Post-Processing

// Enable HDR + tonemapping + bloom
renderer.enable_post_processing()?;

// Tonemapping settings
renderer.set_tonemapping_enabled(true);
renderer.set_tonemapping_exposure(1.2);  // HDR exposure
renderer.set_tonemapping_gamma(2.2);      // Display gamma

// Bloom settings
renderer.set_bloom_enabled(true);
renderer.set_bloom_intensity(0.3);

Material Properties

use charge::renderer::Material;

let material = renderer.material_mut();
material.base_color = glam::Vec4::new(1.0, 0.5, 0.2, 1.0);
material.metallic = 0.8;
material.roughness = 0.2;
material.emissive = glam::Vec3::new(0.0, 0.0, 0.0);

Diagnostics Overlay

use charge::renderer::diagnostics::DiagnosticsMode;

// Enable on-screen diagnostics
renderer.set_diagnostics_mode(DiagnosticsMode::Overlay);

// Or console-only output
renderer.set_diagnostics_mode(DiagnosticsMode::ConsoleOnly);

// Toggle with F6 key (in examples)
renderer.toggle_diagnostics();

๐ŸŽฎ Examples

Run the included examples:

# Simple triangle rendering
cargo run --example triangle

# Load and view GLB models
cargo run --example glb_view
cargo run --example glb_view -- assets/your_model.glb

# Interactive camera controls
cargo run --example interactive

# Post-processing demo (tonemapping + bloom)
cargo run --example postprocess_demo

Example Controls

Key Action
WASD Move camera
Space/Shift Move up/down
Arrow Keys Rotate view
R Toggle auto-rotation
1-6 Adjust post-processing
B Toggle bloom
T Toggle tonemapping
F6 Toggle diagnostics
ESC Exit

๐Ÿ› ๏ธ Development

Building

cargo build --release

Testing

cargo test --lib

Linting

cargo clippy

Compiling Shaders

Shaders are pre-compiled, but if you modify them:

# Windows
./scripts/compile_shaders.ps1

# Linux/Mac (if script exists)
./scripts/compile_shaders.sh

๐Ÿ“ Project Structure

charge/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ lib.rs              # Library entry point
โ”‚   โ”œโ”€โ”€ app/                # ChargeApp high-level wrapper
โ”‚   โ”œโ”€โ”€ asset/              # Model, texture, LOD loading
โ”‚   โ”œโ”€โ”€ camera/             # Camera system
โ”‚   โ”œโ”€โ”€ ecs/                # Entity Component System
โ”‚   โ”œโ”€โ”€ input/              # Input handling
โ”‚   โ””โ”€โ”€ renderer/           # Core Vulkan renderer
โ”‚       โ”œโ”€โ”€ vulkan/         # Low-level Vulkan abstractions
โ”‚       โ”œโ”€โ”€ features/       # Render features (shadows, bloom, etc.)
โ”‚       โ”œโ”€โ”€ diagnostics/    # Performance overlay
โ”‚       โ””โ”€โ”€ resources/      # Resource management
โ”œโ”€โ”€ shaders/                # GLSL shaders + compiled SPIR-V
โ”œโ”€โ”€ examples/               # Example applications
โ””โ”€โ”€ assets/                 # Demo assets (GLB models)

๐Ÿ”ง Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                        ChargeApp                            โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚    EcsWorld     โ”‚  โ”‚    Renderer     โ”‚  โ”‚ InputState โ”‚  โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚  โ”‚            โ”‚  โ”‚
โ”‚  โ”‚  โ”‚ Entities  โ”‚  โ”‚  โ”‚  โ”‚  Vulkan   โ”‚  โ”‚  โ”‚            โ”‚  โ”‚
โ”‚  โ”‚  โ”‚Components โ”‚  โ”‚โ”€โ”€โ”‚  โ”‚  Backend  โ”‚  โ”‚  โ”‚            โ”‚  โ”‚
โ”‚  โ”‚  โ”‚ Systems   โ”‚  โ”‚  โ”‚  โ”‚           โ”‚  โ”‚  โ”‚            โ”‚  โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚  โ”‚            โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                              โ”‚
                              โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    Vulkan Rendering                         โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚ Swapchain โ”‚ โ”‚ Pipelines โ”‚ โ”‚Descriptorsโ”‚ โ”‚  Shaders  โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚  Shadows  โ”‚ โ”‚   Bloom   โ”‚ โ”‚Tonemappingโ”‚ โ”‚  Bindless โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ“œ License

This project is licensed under the Apache License 2.0.


๐Ÿ‘ค Author

Saptak Santra
๐Ÿ“ง saptaksantra7777@gmail.com


๐Ÿค Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request
Commit count: 0

cargo fmt