diff --git a/in_one_weekend/src/camera.zig b/in_one_weekend/src/camera.zig index a7fb8d4..c5fee30 100644 --- a/in_one_weekend/src/camera.zig +++ b/in_one_weekend/src/camera.zig @@ -1,5 +1,6 @@ const std = @import("std"); const math = std.math; +const Random = std.rand.Random; const Point3 = @import("vec3.zig").Point3; const Vec3 = @import("vec3.zig").Vec3; @@ -9,11 +10,23 @@ fn degreesToRadians(degrees: f32) f32 { return degrees * math.pi / 180.0; } +fn random_in_unit_disk(rng: *Random) Vec3 { + while (true) { + const p = Vec3{ .x = rng.float(f32) * 2 - 1, .y = rng.float(f32) * 2 - 1, .z = 0 }; + if (p.length_squared() >= 1) continue; + return p; + } +} + pub const Camera = struct { origin: Point3, lowerLeftCorner: Point3, horizontal: Vec3, vertical: Vec3, + u: Vec3, + v: Vec3, + w: Vec3, + lensRadius: f32, pub fn init( lookFrom: Point3, @@ -21,6 +34,8 @@ pub const Camera = struct { vup: Vec3, vfov: f32, aspectRatio: f32, + aperture: f32, + focusDist: f32, ) Camera { const theta = degreesToRadians(vfov); const h = math.tan(theta / 2); @@ -33,22 +48,29 @@ pub const Camera = struct { const v = w.cross(u); const origin = lookFrom; - const horizontal = u.mul_s(viewportWidth); - const vertical = v.mul_s(viewportHeight); - const lowerLeftCorner = origin.sub(horizontal.div(2)).sub(vertical.div(2)).sub(w); + const horizontal = u.mul_s(viewportWidth).mul_s(focusDist); + const vertical = v.mul_s(viewportHeight).mul_s(focusDist); + const lowerLeftCorner = origin.sub(horizontal.div(2)).sub(vertical.div(2)).sub(w.mul_s(focusDist)); return Camera { .origin = origin, .horizontal = horizontal, .vertical = vertical, .lowerLeftCorner = lowerLeftCorner, + .u = u, + .v = v, + .w = w, + .lensRadius = aperture / 2, }; } - pub fn getRay(self: Camera, s: f32, t: f32) Ray { + pub fn getRay(self: Camera, s: f32, t: f32, rng: *Random) Ray { + const rd = random_in_unit_disk(rng).mul_s(self.lensRadius); + const offset = self.u.mul_s(rd.x).add(self.v.mul_s(rd.y)); + return Ray{ - .origin = self.origin, - .direction = self.lowerLeftCorner.add(self.horizontal.mul_s(s)).add(self.vertical.mul_s(t)).sub(self.origin), + .origin = self.origin.add(offset), + .direction = self.lowerLeftCorner.add(self.horizontal.mul_s(s)).add(self.vertical.mul_s(t)).sub(self.origin).sub(offset), }; } }; \ No newline at end of file diff --git a/in_one_weekend/src/main.zig b/in_one_weekend/src/main.zig index ee265df..bb0e16b 100644 --- a/in_one_weekend/src/main.zig +++ b/in_one_weekend/src/main.zig @@ -123,12 +123,19 @@ pub fn main() anyerror!void { const world = World{ .spheres = spheres[0..spheres.len] }; // Camera + const lookFrom = Point3{ .x = 3, .y = 3, .z = 2 }; + const lookAt = Point3{ .x = 0, .y = 0, .z = -1 }; + const vup = Vec3{ .x = 0, .y = 1, .z = 0 }; + const distToFocus = lookFrom.sub(lookAt).length(); + const aperture = 2.0; const camera = Camera.init( - Point3{ .x = -2, .y = 2, .z = 1 }, - Point3{ .x = 0, .y = 0, .z = -1 }, - Vec3{ .x = 0, .y = 1, .z = 0 }, + lookFrom, + lookAt, + vup, 20.0, - aspectRatio + aspectRatio, + aperture, + distToFocus ); const window = sdl.c.SDL_CreateWindow( @@ -186,7 +193,7 @@ pub fn main() anyerror!void { const u = (@intToFloat(f32, i) + prng.random.float(f32)) / @intToFloat(f32, (imageWidth - 1)); const v = (@intToFloat(f32, j) + prng.random.float(f32)) / @intToFloat(f32, (imageHeight - 1)); - const r = camera.getRay(u, v); + const r = camera.getRay(u, v, &prng.random); const sample = rayColor(r, world, &prng.random, maxDepth); pixelColor.* = pixelColor.*.add(sample);