diff --git a/src/bin/minitracer/main.rs b/src/bin/minitracer/main.rs index f6780a3..bf2e06b 100644 --- a/src/bin/minitracer/main.rs +++ b/src/bin/minitracer/main.rs @@ -161,6 +161,10 @@ fn main() { seed: frame, }, viewport, + trace::Aperture { + radius: 0.001, + focal_distance: std::f32::INFINITY, + }, location, ); } diff --git a/src/bin/minitracer/trace.rs b/src/bin/minitracer/trace.rs index 2b13f6f..f55a324 100644 --- a/src/bin/minitracer/trace.rs +++ b/src/bin/minitracer/trace.rs @@ -18,6 +18,11 @@ pub struct Viewport { pub corner: Vec3, } +pub struct Aperture { + pub radius: f32, + pub focal_distance: f32, // from 0 (exclusive) to +∞ (inclusive) +} + #[derive(Debug, Clone, Copy)] pub struct CameraLocation { pub eye: Vec3, @@ -39,13 +44,13 @@ struct CameraData { v: Vec3, height: f32, w: Vec3, - pad3: f32, + aperture: f32, eye: Vec3, - pad4: f32, + antifocal: f32, } -impl From<(Viewport, CameraLocation)> for CameraData { - fn from(value: (Viewport, CameraLocation)) -> Self { +impl From<(Viewport, CameraLocation, Aperture)> for CameraData { + fn from(value: (Viewport, CameraLocation, Aperture)) -> Self { CameraData { u: value.1.view.x_axis, v: value.1.view.y_axis, @@ -53,8 +58,8 @@ impl From<(Viewport, CameraLocation)> for CameraData { eye: value.1.eye, width: value.0.corner.x / value.0.corner.z, height: value.0.corner.y / value.0.corner.z, - pad3: 0., - pad4: 0., + aperture: value.2.radius, + antifocal: 1. / value.2.focal_distance, } } } @@ -228,6 +233,7 @@ impl Tracer { env: &TracerEnv, params: Params, viewport: Viewport, + aperture: Aperture, camera: CameraLocation, ) { pass.set_pipeline(&self.pipeline); @@ -236,7 +242,7 @@ impl Tracer { 0, bytes_of(&ParamsData { params, - camera: (viewport, camera).into(), + camera: (viewport, camera, aperture).into(), }), ); pass.set_vertex_buffer(0, self.view_buf.slice(..)); diff --git a/src/bin/minitracer/trace.wgsl b/src/bin/minitracer/trace.wgsl index c4a2138..f3fce09 100644 --- a/src/bin/minitracer/trace.wgsl +++ b/src/bin/minitracer/trace.wgsl @@ -9,7 +9,9 @@ struct Params { up: vec3f, height: f32, forward: vec3f, + aperture: f32, eye: vec3f, + antifocal: f32, } struct Sphere { @@ -73,10 +75,14 @@ fn trace_fragment(in: Varying) -> vec3f { var result = vec3(0.); var color = vec3(1.); - pos = params.eye; + let view_mtx = mat3x3(params.right, params.up, params.forward); + let aperture_offset_rel = params.aperture * rand_disc(); + let aperture_offset_abs = view_mtx * vec3(aperture_offset_rel, 0.); + pos = params.eye + aperture_offset_abs; let off_px = vec2(rand_float(), rand_float()) - .5; let off_w = mat2x3(dpdx(in.dir), dpdy(in.dir)); - ray = normalize(in.dir + off_w * off_px); + let dir = in.dir + off_w * off_px; + ray = normalize(dir - params.antifocal * aperture_offset_abs); for (var k = 0; k < params.max_reflections; k++) { var sphere = -1; @@ -140,6 +146,16 @@ fn rand_float() -> f32 { return f32(rand_next()) / 0x1p32; } +fn rand_disc() -> vec2f { + for (var k = 0; k < 16; k++) { + let v = vec2f(rand_float(), rand_float()) - 0.5; + if (length(v) <= 0.5) { + return 2. * v; + } + } + return vec2f(0.0); // safeguard +} + fn rand_sphere() -> vec3f { for (var k = 0; k < 16; k++) { let v = vec3f(rand_float(), rand_float(), rand_float()) - 0.5;