4 releases (2 breaking)

0.3.0 Feb 19, 2024
0.2.0 Jun 10, 2021
0.1.1 May 27, 2021
0.1.0 May 27, 2021

#7 in Rendering engine

LGPL-3.0

1MB
5K SLoC

Crystal Ball

Latest Version API Documentation

Crystal Ball is a path tracing library written in Rust.

It uses rayon for parallelization and can save the rendered image in various formats thanks to the image crate.

Note that Crystal Ball is a hobby project and will most likely see a lot of API changes in future versions.

Features

  • Multithreaded CPU rendering
  • Save rendered images in various formats
  • Environment textures
  • General purpose PBR material
  • Shapes: spheres and triangle meshes
  • Easily create your own textures, materials, and shapes
  • Load glTF files
  • Depth of field
  • Bounding Volume Hierarchies
  • Optional denoising using Open Image Denoise

Usage

Basic Example

A basic example rendering two spheres.

use std::default::Default;
use std::sync::Arc;

use crystal_ball::prelude::*;

fn main() -> Result<(), Error> {
    let objects = vec![
        Object::new(
            Arc::new(Sphere::new()),
            Arc::new(PbrMaterial {
                base_color: Color::new(1.0, 0.45, 0.31),
                ..Default::default()
            }),
        ),
        Object::new(
            Arc::new(
                Sphere::new()
                    .translate(Vec3::new(0.0, -101.0, 0.0))
                    .scale_xyz(Vec3::splat(100.0)),
            ),
            Arc::new(PbrMaterial::default()),
        ),
    ];

    let scene = Scene {
        objects,
        camera: Camera::default().translate(Vec3::new(0.0, 0.0, 5.0)),
        ..Default::default()
    };

    let engine = RenderEngine::default();
    let image = engine.render(&scene);

    image.write("basic.png")?;

    Ok(())
}

This produces the following image:

There are many other examples showcasing Crystal Ball's capabilities, demonstrating how to use the different features.

Coordinate System

Crystal Ball uses a right-handed coordinate system where

  • +X points right
  • +Y points up
  • +Z points to the screen

Denoising

Crystal ball can optionally denoise rendered images using the Rust bindings for Open Image Denoise.

To use this feature you need to install Open Image Denoise and set the environment variable OIDN_DIR to the root directory of the Open Image Denoise installation.

Enable the oidn feature in your Cargo.toml:

[dependencies.crystal_ball]
version = "0.3.0"
features = ["oidn"]

Now you can use the denoise method in your Rust code.

fn main() -> Result<(), Error> {
    // ...
    let mut image = engine.render(&scene);
    image.denoise()?;
    image.write("image_denoised.png")?;
}

Optimization

The performance of your path tracing code will benefit greatly from compiler optimizations, at the cost of longer compile times. To easily switch between quick compilation and highly optimized code generation, you can put the following lines into your Cargo.toml. For a detailed explanation of what this does, see the Cargo Book.

[package]
# ...

[profile.dev]
opt-level = 3

[profile.release]
# Reduce binary size
#panic = "abort"
#strip = "symbols"

# Improve performance but increase compile time
lto = "fat"
codegen-units = 1

Feature Flags

Optional Features

Name description
oidn Image denoising using Open Image Denoise

References/Resources

Dependencies

~17–27MB
~220K SLoC