summaryrefslogtreecommitdiff
path: root/racer-tracer/src/renderer.rs
blob: 0c351c911190f6849c8712ecd2786162e5f3ddd0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use std::{sync::RwLock, time::Duration};

use synchronoise::SignalEvent;

use crate::{
    camera::Camera,
    config::{Config, Renderer as ConfigRenderer},
    error::TracerError,
    geometry::Hittable,
    image::Image,
    ray::Ray,
    vec3::Color,
    vec3::Vec3,
};

use self::{cpu::CpuRenderer, cpu_scaled::CpuRendererScaled};

pub mod cpu;
pub mod cpu_scaled;

fn do_cancel(cancel_event: Option<&SignalEvent>) -> bool {
    match cancel_event {
        Some(event) => event.wait_timeout(Duration::from_secs(0)),
        None => false,
    }
}

fn ray_color(scene: &dyn Hittable, ray: &Ray, depth: usize) -> Vec3 {
    if depth == 0 {
        return Vec3::default();
    }

    if let Some(rec) = scene.hit(ray, 0.001, std::f64::INFINITY) {
        if let Some((scattered, attenuation)) = rec.material.scatter(ray, &rec) {
            return attenuation * ray_color(scene, &scattered, depth - 1);
        }
        return Color::default();
    }

    // Sky
    let first_color = Vec3::new(1.0, 1.0, 1.0);
    let second_color = Vec3::new(0.5, 0.7, 1.0);
    let unit_direction = ray.direction().unit_vector();
    let t = 0.5 * (unit_direction.y() + 1.0);
    (1.0 - t) * first_color + t * second_color
}

pub struct RenderData<'a> {
    pub buffer: &'a RwLock<Vec<u32>>,
    pub camera: &'a RwLock<Camera>,
    pub image: &'a Image,
    pub scene: &'a dyn Hittable,
    pub config: &'a Config,
    pub cancel_event: Option<&'a SignalEvent>,
    pub buffer_updated: Option<&'a SignalEvent>,
}

pub trait Renderer: Send + Sync {
    fn render(&self, render_data: RenderData) -> Result<(), TracerError>;
}

impl From<&ConfigRenderer> for &dyn Renderer {
    fn from(r: &ConfigRenderer) -> Self {
        match r {
            ConfigRenderer::Cpu => &CpuRenderer {} as &dyn Renderer,
            ConfigRenderer::CpuPreview => &CpuRendererScaled {} as &dyn Renderer,
        }
    }
}