A toy ray-tracing renderer in Rust
Download this image and put it under root directory of this repo. It will be used as a texture map in the demo.
cargo run --release --example main > image.png
This will generate book 2's cover image. It takes roughly 1 hour on my i5-3317U.
--release
can significantly increase rendering speed.
If you are on windows, just cargo run --release
and find a image.png
under root directory.
To generate book 1's cover image (random spheres):
cargo run --release --example book-one > image.ppm
This example takes about 10 min on my i5-3317U.
To generate Cornell box:
cargo run --release --example cornell-box > image.ppm
This example takes about 1 hour on my i5-3317U.
- lambertian, metal, dielectric (glass-like), light-emitting materials
- sub-surface scattering inside constant density medium like fog and smoke
- bounding volume hierarchy to speedup ray-object intersection detection
- sphere, rectangle, cube geometry
- perspective camera with depth-of-field blurring effect
Build a blue smoke sphere with radius 70 and place it at (360, 150, 145):
let sphere = Arc::new(
Sprite::builder()
.geometry(ConstantMedium::new(Sphere::new(70.0).into(), 0.2).into())
.material(Isotropic::new(Vec3::new(0.2, 0.4, 0.9)).into())
.transform(Mat4::translation(Vec3::new(360.0, 150.0, 145.0)))
.build(),
);
Speed up ray-object intersection detection by constructing a bounding volume hierarchy:
let sprites: Vec<Arc<dyn Bound<AxisAlignedBoundingBox>>> = unimplemented!();
let bvh = BoundingVolumeHierarchyNode::new(sprites).unwrap();
Set up a perspective camera:
let camera = PerspectiveCamera::new(
eye, // eye position
center, // what eye is looking at
up, // camera's head up direction
(40.0 as f64).to_radians(), // field of view in radians
width as f64 / height as f64, // aspect ratio
10.0, // focus distance
0.01, // lens radius
);
Get color at image position (x, y) (image coordinate origin is at lower-left corner, +x points rightward, +y points upward):
let world: Arc<dyn Hit> = unimplemented!(); // your scene
let u = (x as f64) / width as f64; // convert to camera coordinate
let v = (y as f64) / height as f64;
let ray = camera.ray(u, v);
let pixel = color(&ray, world.as_ref(), 100); // ray scatters at most 100 times
- surface/geometry modifiers like bump map
- random noise textures
- GPU parallelism to speedup (real time?)
- port to WebAssembly
- physical realism for wave optics
- mesh/mass triangle rendering
- load from 3D files like
.obj
Please feel free to drop an issue or a comment!
[book-i] | Ray Tracing in One Weekend |
[book-ii] | Ray Tracing: The Next Week |
[pbr] | Physically Based Rendering: From Theory to Implementation |