aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs19
-rw-r--r--src/material/diffuse_light.rs27
-rw-r--r--src/material/mod.rs12
-rw-r--r--src/material/sky_light.rs19
-rw-r--r--src/trace/pathtrace.rs35
5 files changed, 92 insertions, 20 deletions
diff --git a/src/main.rs b/src/main.rs
index 9ffcac4..dc9ea43 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,7 +4,7 @@ use rendering::trace::DefaultTracer;
use rendering::core::{Vector2i, Vector3f, Spectrum};
use rendering::render::{RenderContext, RenderCoord};
use rendering::sample::UniformSampler;
-use rendering::material::{Reflectant, Lambertian};
+use rendering::material::*;
use std::sync::Arc;
@@ -15,7 +15,7 @@ fn main() {
target: Vector3f::new_xyz(0.0, 0.0, -1.0),
origin: Vector3f::new_xyz(1.7, 0.0, 0.3),
up: Vector3f::new_xyz(0.0, 1.0, 0.0),
- fov: 40.0,
+ fov: 60.0,
filmsize: res,
focus: None,
aperture: Some(20.0),
@@ -23,16 +23,21 @@ fn main() {
let brown = Arc::new(Lambertian::new(Spectrum::new_rgb(0.5, 0.3, 0.0)));
let blue = Arc::new(Lambertian::new(Spectrum::new_rgb(0.0, 0.3, 0.7)));
- let metal = Arc::new(Reflectant::new(Spectrum::new_rgb(0.75, 0.75, 0.75), None));
+ let metal = Arc::new(Reflectant::new(Spectrum::new_rgb(0.8, 0.8, 0.9), Some(1.0)));
+ let sun = Arc::new(DiffuseLight::new_white(13.0));
let mut scn = Scene::new();
scn.add_objects(vec![
- Object::new(metal, Box::new(Sphere::new(0.5, Vector3f::new_xyz(0.0, 0.0, -1.0)))),
+ Object::new(metal, Box::new(Sphere::new(0.2, Vector3f::new_xyz(0.0, 0.0, -1.0)))),
Object::new(blue, Box::new(Sphere::new(0.5, Vector3f::new_xyz(1.0, 0.0, -1.0)))),
Object::new(brown, Box::new(Sphere::new(100.0, Vector3f::new_xyz(0.0, -100.5, -1.0)))),
+ Object::new(sun, Box::new(Sphere::new(0.4, Vector3f::new_xyz(-1.0, 0.7, 0.0)))),
]);
- let tracer = DefaultTracer::new(&scn, Some(50));
+ let tracer = DefaultTracer::new(&scn, Some(50),
+ //Some(Box::new(SkyLight::new()))
+ None
+ );
let mut sampler = UniformSampler::new();
@@ -40,9 +45,9 @@ fn main() {
let mut film = Film::new(res);
{
- let coord = RenderCoord::new(&mut film, Vector2i::new_xy(32, 32), 100);
+ let coord = RenderCoord::new(&mut film, Vector2i::new_xy(64, 64), 400);
- coord.run_threaded(&ctx, &mut sampler, 4);
+ coord.run_threaded(&ctx, &mut sampler, 8);
}
let image = film.finalize_image();
diff --git a/src/material/diffuse_light.rs b/src/material/diffuse_light.rs
new file mode 100644
index 0000000..fe462a8
--- /dev/null
+++ b/src/material/diffuse_light.rs
@@ -0,0 +1,27 @@
+use super::Material;
+use crate::core::{Ray, Spectrum};
+use crate::Float;
+
+pub struct DiffuseLight {
+ color: Spectrum,
+}
+
+impl DiffuseLight {
+ pub fn new(c: Spectrum) -> Self {
+ Self {
+ color: c,
+ }
+ }
+
+ pub fn new_white(s: Float) -> Self {
+ Self {
+ color: Spectrum::new_rgb(s, s, s),
+ }
+ }
+}
+
+impl Material for DiffuseLight {
+ fn emitted(&self, _: &Ray) -> Option<Spectrum> {
+ Some(self.color)
+ }
+}
diff --git a/src/material/mod.rs b/src/material/mod.rs
index 7f920e2..3e92bf6 100644
--- a/src/material/mod.rs
+++ b/src/material/mod.rs
@@ -4,10 +4,20 @@ use crate::sample::Sampler;
mod lambertian;
mod reflectant;
+mod diffuse_light;
+mod sky_light;
pub use lambertian::Lambertian;
pub use reflectant::Reflectant;
+pub use diffuse_light::DiffuseLight;
+pub use sky_light::SkyLight;
pub trait Material: Sync + Send {
- fn scatter(&self, ray: &Ray, i: &Intersection, sampler: &mut dyn Sampler) -> Option<(Spectrum, Ray)>;
+ fn scatter(&self, _: &Ray, _: &Intersection, _: &mut dyn Sampler) -> Option<(Spectrum, Ray)> {
+ None
+ }
+
+ fn emitted(&self, _: &Ray) -> Option<Spectrum> {
+ None
+ }
}
diff --git a/src/material/sky_light.rs b/src/material/sky_light.rs
new file mode 100644
index 0000000..e499b6e
--- /dev/null
+++ b/src/material/sky_light.rs
@@ -0,0 +1,19 @@
+use super::Material;
+use crate::core::{Ray, Spectrum};
+
+pub struct SkyLight {
+}
+
+impl SkyLight {
+ pub fn new() -> Self {
+ Self {}
+ }
+}
+
+impl Material for SkyLight {
+ fn emitted(&self, ray: &Ray) -> Option<Spectrum> {
+ let t = (ray.direction.norm().y + 1.0) * 0.5;
+
+ Some(Spectrum::new_rgb(1.0, 1.0, 1.0) * (1.0-t) + Spectrum::new_rgb(0.5, 0.7, 1.0) * t)
+ }
+}
diff --git a/src/trace/pathtrace.rs b/src/trace/pathtrace.rs
index 2d15976..f53e433 100644
--- a/src/trace/pathtrace.rs
+++ b/src/trace/pathtrace.rs
@@ -1,23 +1,23 @@
use crate::world::{Hittable, Scene};
use crate::core::{Ray, Spectrum};
+use crate::material::Material;
use crate::sample::Sampler;
-use crate::material::{Lambertian, Material};
use super::Tracer;
pub struct PathTracer<'a> {
depth: i32,
scn: &'a Scene,
- default_mat: Box<dyn Material>,
+ background: Option<Box<dyn Material>>,
}
impl PathTracer<'_> {
- pub fn new(scn: &Scene, depth: Option<i32>) -> PathTracer {
+ pub fn new(scn: &Scene, depth: Option<i32>, background: Option<Box<dyn Material>>) -> PathTracer {
let depth = depth.unwrap_or(-1);
PathTracer {
depth,
scn,
- default_mat: Box::new(Lambertian::new(Spectrum::ZERO)),
+ background,
}
}
@@ -28,17 +28,28 @@ impl PathTracer<'_> {
}
if let Some(i) = self.scn.intersect(ray) {
- if let Some((scalar, nray)) = i.m.unwrap_or(self.default_mat.as_ref()).scatter(ray, &i, sampler) {
- return self.trace_recur(sampler, &nray, depth-1) * scalar;
- } else {
- return Spectrum::ZERO;
+ // Extract material or default
+ if let Some(mat) = i.m {
+ let mut col = Spectrum::ZERO;
+
+ if let Some((scalar, nray)) = mat.scatter(ray, &i, sampler) {
+ col += &(self.trace_recur(sampler, &nray, depth-1) * scalar);
+ }
+
+ if let Some(c) = mat.emitted(ray) {
+ col += &c;
+ }
+
+ return col;
}
}
- // Simulates a sky
- let t = (ray.direction.norm().y + 1.0) * 0.5;
- Spectrum::new_rgb(1.0, 1.0, 1.0) * (1.0-t) + Spectrum::new_rgb(0.5, 0.7, 1.0) * t
-
+ // If no color return background
+ if let Some(back) = &self.background {
+ back.emitted(ray).unwrap_or(Spectrum::ZERO)
+ } else {
+ Spectrum::ZERO
+ }
}
}