summaryrefslogtreecommitdiff
path: root/racer-tracer/src/main.rs
diff options
context:
space:
mode:
authorSakarias Johansson <sakarias.johansson@goodbyekansas.com>2023-01-08 17:51:44 +0100
committerSakarias Johansson <sakarias.johansson@goodbyekansas.com>2023-01-08 17:51:44 +0100
commit899f81eed6c221dce22333ad03704b12d7634a54 (patch)
treee9ea6b377bada412629341e666ae5d2eb929420a /racer-tracer/src/main.rs
parent928b4191bf5a0d27da6d680ccaade7f94860359e (diff)
downloadracer-tracer-899f81eed6c221dce22333ad03704b12d7634a54.tar.gz
racer-tracer-899f81eed6c221dce22333ad03704b12d7634a54.tar.xz
racer-tracer-899f81eed6c221dce22333ad03704b12d7634a54.zip
🌍 Add Geometry
- Created a trait for all geometry that has to implement a hit function. Depending on if the ray hits or not it returns an option with the color. - Add support for multiple samples per pixel Current issues: - Using cooperative multitasking which isn't that helpful in this situation since it's like running without async but without overhead. Should switch to rayon. - All data gets copied once per job. Will decide later what to do (copy or put locks and share data between jobs).
Diffstat (limited to 'racer-tracer/src/main.rs')
-rw-r--r--racer-tracer/src/main.rs76
1 files changed, 58 insertions, 18 deletions
diff --git a/racer-tracer/src/main.rs b/racer-tracer/src/main.rs
index 1951da5..9d45762 100644
--- a/racer-tracer/src/main.rs
+++ b/racer-tracer/src/main.rs
@@ -1,51 +1,86 @@
#[macro_use]
mod error;
mod camera;
+mod geometry;
mod image;
mod ray;
+mod scene;
mod util;
mod vec3;
-use crate::vec3::Vec3;
use std::vec::Vec;
use futures::{select, stream::FuturesUnordered, stream::StreamExt};
+use geometry::Hittable;
use minifb::{Key, Window, WindowOptions};
-fn ray_color(ray: &ray::Ray) -> Vec3 {
- let unit_direction = vec3::unit_vector(ray.direction());
+use crate::camera::Camera;
+use crate::geometry::sphere::Sphere;
+use crate::image::Image;
+use crate::ray::Ray;
+use crate::scene::Scene;
+use crate::util::random_double;
+use crate::vec3::Vec3;
+
+fn ray_color(scene: &Scene, ray: &Ray) -> Vec3 {
+ if let Some(hit_record) = scene.hit(ray, 0.0, std::f64::INFINITY) {
+ //return hit_record.color;
+ return 0.5 * (hit_record.normal + Vec3::new(1.0, 1.0, 1.0));
+ }
+
+ // Sky
+ let unit_direction = ray.direction().unit_vector();
let t = 0.5 * (unit_direction.y() + 1.0);
(1.0 - t) * Vec3::new(1.0, 1.0, 1.0) + t * Vec3::new(0.5, 0.7, 1.0)
}
+// TODO: Rustify
async fn raytrace(
- camera: camera::Camera,
- image: image::Image,
+ scene: Scene,
+ camera: Camera,
+ image: Image,
row: usize,
) -> Result<(usize, Vec<u32>), error::TracerError> {
let mut buffer: Vec<u32> = vec![0; image.width as usize];
+ let mut colors: Vec<Vec3> = vec![Vec3::default(); image.width as usize];
for i in 0..buffer.len() {
- let u: f64 = i as f64 / (image.width - 1) as f64;
- let v: f64 = row as f64 / (image.height - 1) as f64;
- let ray = ray::Ray::new(
- camera.origin,
- camera.lower_left_corner + u * camera.horizontal + v * camera.vertical - camera.origin,
- );
- let col = ray_color(&ray);
- buffer[i] = col.as_color();
+ for _ in 0..image.samples_per_pixel {
+ let u: f64 = (i as f64 + random_double()) / (image.width - 1) as f64;
+ let v: f64 = (row as f64 + random_double()) / (image.height - 1) as f64;
+ colors[i] += ray_color(&scene, &camera.get_ray(u, v));
+ }
+ }
+
+ for i in 0..image.width {
+ buffer[i] = (colors[i] / image.samples_per_pixel as f64).as_color();
}
Ok((row, buffer))
}
+fn create_scene() -> Scene {
+ let mut scene = Scene::new();
+ let sphere1 = Sphere::new(Vec3::new(0.0, 0.0, -1.0), 0.5, Vec3::new(0.0, 1.0, 0.0));
+ let sphere2 = Sphere::new(
+ Vec3::new(0.0, -100.5, -1.0),
+ 100.0,
+ Vec3::new(0.0, 1.0, 0.0),
+ );
+ scene.add(Box::new(sphere1));
+ scene.add(Box::new(sphere2));
+ scene
+}
+
async fn run(
rows_per_update: u32,
aspect_ratio: f64,
- screen_height: usize,
+ screen_width: usize,
+ samples: usize,
) -> Result<(), error::TracerError> {
- let image = image::Image::new(aspect_ratio, screen_height);
+ let image = image::Image::new(aspect_ratio, screen_width, samples);
let camera = camera::Camera::new(&image, 2.0, 1.0);
+ let scene = create_scene();
let mut screen_buffer: Vec<u32> = vec![0; image.width * image.height];
let mut window = Window::new(
@@ -61,13 +96,18 @@ async fn run(
// One future per row is a bit high.
// Could do something less spammy.
for h in 0..image.height {
- futs.push(raytrace(camera.clone(), image.clone(), h));
+ // TODO: Either clone all or lock em all.
+ futs.push(raytrace(scene.clone(), camera.clone(), image.clone(), h));
}
+ // TODO: use rayon
+ // Since it's cooperative multitasking this is not really helpful at the moment.
+ // You will get pretty much get the same result without the tokio asyncness.
+ // using rayon with threads is a different matter.
let mut complete = false;
while window.is_open() && !window.is_key_down(Key::Escape) {
if !complete {
- for _ in 1..rows_per_update {
+ for _ in 0..rows_per_update {
select! {
res = futs.select_next_some() => {
let row_buffer = res.expect("Expected to get data");
@@ -95,7 +135,7 @@ async fn run(
#[tokio::main]
async fn main() {
- if let Err(e) = run(50, 16.0 / 9.0, 1200).await {
+ if let Err(e) = run(100, 16.0 / 9.0, 1200, 100).await {
eprintln!("{}", e);
std::process::exit(e.into())
}