A ray marching renderer in rust
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
rmarcher/src/main.rs

115 lines
4.1 KiB

mod material;
mod light;
mod object;
mod structs;
mod consts;
mod lua;
use object::*;
use crate::consts::*;
use crate::structs::*;
use crate::material::*;
use image::{ColorType, ImageFormat};
use crate::light::Light;
use crate::lua::scene_from_file;
fn default_cam() -> Cam {
Cam::new_pointing(Y*3. - X*5., O, 0.5)
}
fn default_scene1() -> Scene {
let s0 = WithMaterial::new(
Sphere::new_xyz(0., 0., 0., 1.),
RED
);
let s1 = WithMaterial::new(
Sphere::new_xyz(0., 1., 1., 0.5),
MIRROR
);
let spheres = Union::new(s0, s1);
let floor = WithMaterial::new(
Plane::new_xyz(0., 1., 0., 2.),
WHITE
);
let backwall = WithMaterial::new(
Plane::new_xyz(-1., 0., 0., 2.),
BLUE
);
let sidewalls = WithMaterial::new(
Union::new(
Plane::new_xyz(0., 0., -1., 2.5),
Plane::new_xyz(0., 0., 1., 2.5)
),
GREEN
);
let walls = Union::new(
Union::new(floor, backwall),
sidewalls
);
let scene = Union::new(spheres, walls);
let light = WithMaterial::new(
Plane::new_xyz(0., -1., 0., 8.),
LIGHTSOURCE
);
let scene = Union::new(scene, light);
Scene::new(scene)
}
fn default_scene2() -> Scene {
let s1 = Sphere::new_xyz(0., 0., 0., 1.);
let scaled = AffineTransform::new_linear(s1, scale(1.2));
let moved = AffineTransform::new_translate(scaled, Vec3::new(3., 1., 1.));
let sphere = WithMaterial::new(moved, BLUE);
let wall = WithMaterial::new(Plane::new_xyz(0., 0., -1., 2.5), GREEN);
let backwall = WithMaterial::new(Plane::new_xyz(-1., 0., 0., 3.), WHITE);
let mirror = WithMaterial::new(Plane::new_xyz(0., 1., 0., 2.), MIRROR);
let light = WithMaterial::new(Sphere::new_xyz(-1., 1.5, 1., 0.5), LIGHTSOURCE);
Scene::new(Union::new(Union::new(sphere, Union::new(wall, backwall)), Union::new(light, mirror)))
}
fn default_scene3() -> Scene {
let s1 = WithMaterial::new(Sphere::new_xyz(4., 0., 0., 1.), MIRROR);
let s2 = WithMaterial::new(Sphere::new_xyz(3., 1., 1., 0.5), GREEN);
let navion = WithMaterial::new(Plane::new_xyz(0., 1., -1., 3.), BLUE);
let backwall = WithMaterial::new(Plane::new_xyz(-1., -1., -0.5, 8.), RED);
let boiboite = Cuboid::new_xyz(4., 1.1, -1.1, 0.5, 0.275, 0.275);
let decal = AffineTransform::new_translate(boiboite, Vec3::new(-0.25, 0., 0.5));
let nope = Exclusion::new(s1, Sphere::new_xyz(3.75, 0.75, 0.75, 1.));
let walls = Union::new(navion, backwall);
let spheres = Union::new(AffineTransform::new_linear(nope, scale(0.75)), s2);
let scene = Union::new(spheres, Union::new(walls, decal));
let light = WithMaterial::new(Plane::new_xyz(0., -1., 0., 8.), BRIGHT_AF_LIGHTSOURCE);
let scene = WithLight::new_one(scene, Light::new(Y*3.-X*5., ColorVec::new([2., 3., 4., 0.])));
Scene::new(Union::new(scene, light))
}
fn main() {
// get scene and camera
let scene = scene_from_file("scenes/randomspheres.lua".to_owned()).unwrap();
//let scene = default_scene3();
let cam = default_cam();
// get stats on the scene we're about to render
let total_rpp = (RAYS_PER_PIXEL * SUPERSAMPLING * SUPERSAMPLING) as u64;
let lights = scene.get_lights().len() as u32;
let nodes = scene.node_count();
let min_rays = IMG_SIZE as u64 * RAYS_PER_PIXEL as u64 * SUPERSAMPLING as u64;
let max_rays = min_rays * MAX_BOUNCES as u64 * (1+lights) as u64;
println!("Image size: {}x{} ({} pixels)", IMG_WIDTH, IMG_HEIGHT, IMG_SIZE);
println!("Rpp: {}, {}x supersampling ({} total rays per image pixel)", RAYS_PER_PIXEL, SUPERSAMPLING, total_rpp);
println!("Max bounces: {}, dist: {}, steps: {}", MAX_BOUNCES, MAX_DIST, MAX_STEPS);
println!("Lights: {}, Nodes: {}", lights, nodes);
println!("Threads: {}, {} slices per thread", THREAD_COUNT, SLICES_PER_THREAD);
println!("Total rays: min {} max {}", min_rays, max_rays);
// generate image and save it
let data = cam.render(&scene);
image::save_buffer_with_format(
"a.png",
&data,
IMG_WIDTH as u32,
IMG_HEIGHT as u32,
ColorType::Rgb8,
ImageFormat::Png
).unwrap();
}