aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/camera/film.rs6
-rw-r--r--src/core/spectrum.rs12
-rw-r--r--src/core/vector2.rs4
-rw-r--r--src/lib.rs1
-rw-r--r--src/main.rs7
-rw-r--r--src/render.rs23
-rw-r--r--src/sample/mod.rs11
-rw-r--r--src/sample/uniform.rs32
8 files changed, 80 insertions, 16 deletions
diff --git a/src/camera/film.rs b/src/camera/film.rs
index 3586374..7193e1d 100644
--- a/src/camera/film.rs
+++ b/src/camera/film.rs
@@ -45,7 +45,7 @@ impl Pixel {
}
fn finalize_rgb(&self) -> [u8; 3] {
- let (r, g, b) = self.rgb.to_rgb(255.0);
+ let (r, g, b) = (&self.rgb / (self.samples as Float)).to_rgb(255.0);
[
r as u8,
g as u8,
@@ -128,8 +128,8 @@ impl FilmTile {
}
/// Add a single sample sampled from the scene
- pub fn add_sample(&mut self, point: &Vector2f, c: Spectrum) {
- let point = Vector2i::from(point.floor());
+ pub fn add_sample(&mut self, inp: &Vector2f, c: Spectrum) {
+ let point = Vector2i::from(inp.floor());
// Subtract the offset
let point = point - self.bounds.min;
diff --git a/src/core/spectrum.rs b/src/core/spectrum.rs
index fb82a9e..41b3342 100644
--- a/src/core/spectrum.rs
+++ b/src/core/spectrum.rs
@@ -33,6 +33,18 @@ impl std::ops::Mul<Float> for &Spectrum {
}
}
+impl std::ops::Div<Float> for &Spectrum {
+ type Output = Spectrum;
+
+ fn div(self, op: Float) -> Self::Output {
+ Self::Output::new_rgb(
+ self.c[0] / op,
+ self.c[1] / op,
+ self.c[2] / op,
+ )
+ }
+}
+
impl std::ops::AddAssign<&Self> for Spectrum {
fn add_assign(&mut self, op: &Self) {
self.c[0] += op.c[0];
diff --git a/src/core/vector2.rs b/src/core/vector2.rs
index 3aadb46..858068e 100644
--- a/src/core/vector2.rs
+++ b/src/core/vector2.rs
@@ -60,8 +60,8 @@ impl Vector2f {
pub fn floor(&self) -> Self {
Self::new_xy(
- self.x.ceil(),
- self.y.ceil()
+ self.x.floor(),
+ self.y.floor()
)
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 555bd89..5883167 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,6 +3,7 @@ pub mod camera;
pub mod render;
pub mod scene;
pub mod trace;
+pub mod sample;
use std::ops::{Add, Sub, Mul, DivAssign};
use std::cmp;
diff --git a/src/main.rs b/src/main.rs
index 9985a80..c1383ad 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,6 +4,7 @@ use pathtrace::trace::Tracer;
use pathtrace::scene::shapes::Sphere;
use pathtrace::core::{Vector2i, Vector3f};
use pathtrace::render::{RenderContext, RenderTask};
+use pathtrace::sample::UniformSampler;
fn main() {
let res = Vector2i::new_xy(500, 500);
@@ -22,13 +23,15 @@ fn main() {
let tracer = Tracer::new();
+ let mut sampler = UniformSampler::new();
+
let ctx = RenderContext { cam: &cam, scn: &scn, trc: &tracer };
let mut film = Film::new(res);
let tile = film.get_tile(&film.frame);
- let mut task = RenderTask::new(Box::new(tile), 1);
- task.render(&ctx);
+ let mut task = RenderTask::new(Box::new(tile), 500);
+ task.render(&ctx, &mut sampler);
film.commit_tile(&task.tile);
diff --git a/src/render.rs b/src/render.rs
index 7d05aba..c8a75da 100644
--- a/src/render.rs
+++ b/src/render.rs
@@ -5,8 +5,9 @@ use crate::camera::film::FilmTile;
use crate::camera::Camera;
use crate::scene::Scene;
use crate::trace::Tracer;
+use crate::sample::Sampler;
-use crate::core::{Vector2f, Vector3f, Spectrum};
+use crate::core::{Vector2f, Spectrum};
use crate::Float;
pub struct RenderTask {
@@ -25,20 +26,24 @@ impl RenderTask {
Self { tile, samples }
}
- fn render_at(&self, ctx: &RenderContext, x: i32, y: i32) -> Spectrum {
- // Create a ray
- let (r, _) = ctx.cam.generate_ray(&Vector2f::new_xy(x as Float, y as Float));
+ fn render_at(&mut self, ctx: &RenderContext, x: i32, y: i32, sampler: &mut dyn Sampler) {
+ let corner = Vector2f::new_xy(x as Float, y as Float);
- ctx.trc.trace(ctx.scn, &r)
+ for _ in 0..self.samples {
+ let p = corner + sampler.get_sample_2d();
+
+ // Create a ray
+ let (r, _) = ctx.cam.generate_ray(&p);
+
+ self.tile.add_sample(&p, ctx.trc.trace(ctx.scn, &r));
+ }
}
- pub fn render(&mut self, ctx: &RenderContext) {
+ pub fn render(&mut self, ctx: &RenderContext, sampler: &mut dyn Sampler) {
let b = self.tile.bounds.clone();
for x in b.min.x .. b.max.x {
for y in b.min.y .. b.max.y {
- let p = Vector2f::new_xy(x as Float, y as Float);
-
- self.tile.add_sample(&p, self.render_at(ctx, x, y))
+ self.render_at(ctx, x, y, sampler);
}
}
}
diff --git a/src/sample/mod.rs b/src/sample/mod.rs
new file mode 100644
index 0000000..6f2c3eb
--- /dev/null
+++ b/src/sample/mod.rs
@@ -0,0 +1,11 @@
+use crate::Float;
+use crate::core::Vector2f;
+
+mod uniform;
+
+pub use uniform::UniformSampler;
+
+pub trait Sampler {
+ fn get_sample(&mut self) -> Float;
+ fn get_sample_2d(&mut self) -> Vector2f;
+}
diff --git a/src/sample/uniform.rs b/src/sample/uniform.rs
new file mode 100644
index 0000000..221fdf8
--- /dev/null
+++ b/src/sample/uniform.rs
@@ -0,0 +1,32 @@
+use crate::core::Vector2f;
+use crate::Float;
+use super::Sampler;
+
+use rand::prelude::*;
+use rand::distributions::Uniform;
+use rand_pcg::Pcg32;
+
+#[derive(Clone)]
+pub struct UniformSampler {
+ r: Pcg32,
+ d: Uniform<Float>,
+}
+
+impl UniformSampler {
+ pub fn new() -> Self {
+ Self {
+ r: Pcg32::seed_from_u64(1),
+ d: Uniform::from(0.0..1.0),
+ }
+ }
+}
+
+impl Sampler for UniformSampler {
+ fn get_sample(&mut self) -> Float {
+ self.d.sample(&mut self.r)
+ }
+
+ fn get_sample_2d(&mut self) -> Vector2f {
+ Vector2f::new_xy(self.get_sample(), self.get_sample())
+ }
+}