0.1.1 |
|
---|---|
0.1.0 |
|
#10 in #path-tracing
115KB
2.5K
SLoC
Spuristo is a CPU based multithreaded rendering engine. Made with the goal of learning Rust and physically based rendering :) The renderer is designed to be as modular as possible such that adding new features or algorithms is straightforward.
Features
- Area light sampling
- Path tracing with next event estimation
- Microfacet BSDF with multiple importance sampling and GGX distribution
- Disney diffuse BRDF with energy normalization used in Frostbite
- Vertex and normal parsing from .OBJ files
- kd-tree that handles meshes containing up to 5 million triangles with reasonable render times
- Tone mapping
- Perlin noise generator
Usage
Once the repository is cloned, the examples/
folder contains scenes. To run the hello_sphere.rs
example execute the command:
cargo run --example hello_sphere
The renderer can be configured either through its setter methods or partially through the CLI:
Usage: hello_sphere [-s <samples>] [-t <threads>] [-w <width>] [-h <height>] [-d]
Optional CLI configuration of renderer. Renderer setter methods have priority.
Options:
-s, --samples number of samples per pixel (defaults to 1)
-t, --threads number of threads used (defaults to all)
-w, --width width of the rendered image (defaults to 1000)
-h, --height height of the rendered image (defaults to 1000)
-d, --direct use direct light integrator instead of path tracing.
--help display usage information
Using the API
The hello_sphere.rs
example is written as follows:
use spuristo::*;
use spuristo::tracer::*;
use glam::DVec3;
fn main() -> Result<(), png::EncodingError> {
let camera = Camera::default();
let mut scene = Scene::default();
scene.add(
Plane::new(
DVec3::NEG_Y,
DVec3::Y,
Material::diffuse(Texture::Solid(srgb_to_linear(190, 200, 210)))
)
);
scene.add(
Sphere::new(
8.0 * DVec3::Y + 1.5 * DVec3::NEG_Z,
4.0,
Material::Light(Texture::Solid(srgb_to_linear(255, 255, 255)))
)
);
scene.add(
Sphere::new(
DVec3::ZERO,
1.0,
Material::diffuse(Texture::Solid(srgb_to_linear(0, 0, 255)))
)
.scale(0.3, 0.3, 0.3)
.translate(0.0, -0.7, -1.5)
);
let mut renderer = Renderer::new(scene, camera);
renderer.set_samples(36);
renderer.render()
.save("hello.png")
}
And it renders an image of a blue sphere:
TODO/WIP
- Finalize refraction of transparent microfacet materials
- Isotropic mediums (fog, smoke, clouds, ...)
- Multiple importance sampling in path tracer
- Sampling from distribution of visible normals in microfacets
- (Texture mapping)
- (Bidirectional path tracing)
- (Subsurface scattering)
References
- Physically Based Rendering
- Ray Tracing in One Weekend
- Moving Frostbite to Physically Based Rendering
- Eric Veach's PhD Thesis
- ekhzang/rpt
Gallery
Stanford dragon with 871K triangles. Rendered in 45 minutes using 30 threads of Intel Xeon Gold 6248. 1024 samples per pixel. |
Cornell box displaying reflection and refraction. Rendered in 50 minutes using 30 threads of Intel Xeon Gold 6248. 4096 samples per pixel. |
Statue of Nefertiti with 6.4M triangles. Rendered in 196 minutes using 40 threads of Intel Xeon Gold 6248. 1024 samples per pixel. |
Dependencies
~15–25MB
~437K SLoC