add defocus blur

master
Fabien Freling 2021-05-27 23:02:42 +02:00
parent d6ba8e354c
commit 2ab82d4c92
2 changed files with 40 additions and 11 deletions

View File

@ -1,5 +1,6 @@
const std = @import("std"); const std = @import("std");
const math = std.math; const math = std.math;
const Random = std.rand.Random;
const Point3 = @import("vec3.zig").Point3; const Point3 = @import("vec3.zig").Point3;
const Vec3 = @import("vec3.zig").Vec3; const Vec3 = @import("vec3.zig").Vec3;
@ -9,11 +10,23 @@ fn degreesToRadians(degrees: f32) f32 {
return degrees * math.pi / 180.0; 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 { pub const Camera = struct {
origin: Point3, origin: Point3,
lowerLeftCorner: Point3, lowerLeftCorner: Point3,
horizontal: Vec3, horizontal: Vec3,
vertical: Vec3, vertical: Vec3,
u: Vec3,
v: Vec3,
w: Vec3,
lensRadius: f32,
pub fn init( pub fn init(
lookFrom: Point3, lookFrom: Point3,
@ -21,6 +34,8 @@ pub const Camera = struct {
vup: Vec3, vup: Vec3,
vfov: f32, vfov: f32,
aspectRatio: f32, aspectRatio: f32,
aperture: f32,
focusDist: f32,
) Camera { ) Camera {
const theta = degreesToRadians(vfov); const theta = degreesToRadians(vfov);
const h = math.tan(theta / 2); const h = math.tan(theta / 2);
@ -33,22 +48,29 @@ pub const Camera = struct {
const v = w.cross(u); const v = w.cross(u);
const origin = lookFrom; const origin = lookFrom;
const horizontal = u.mul_s(viewportWidth); const horizontal = u.mul_s(viewportWidth).mul_s(focusDist);
const vertical = v.mul_s(viewportHeight); const vertical = v.mul_s(viewportHeight).mul_s(focusDist);
const lowerLeftCorner = origin.sub(horizontal.div(2)).sub(vertical.div(2)).sub(w); const lowerLeftCorner = origin.sub(horizontal.div(2)).sub(vertical.div(2)).sub(w.mul_s(focusDist));
return Camera { return Camera {
.origin = origin, .origin = origin,
.horizontal = horizontal, .horizontal = horizontal,
.vertical = vertical, .vertical = vertical,
.lowerLeftCorner = lowerLeftCorner, .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{ return Ray{
.origin = 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), .direction = self.lowerLeftCorner.add(self.horizontal.mul_s(s)).add(self.vertical.mul_s(t)).sub(self.origin).sub(offset),
}; };
} }
}; };

View File

@ -123,12 +123,19 @@ pub fn main() anyerror!void {
const world = World{ .spheres = spheres[0..spheres.len] }; const world = World{ .spheres = spheres[0..spheres.len] };
// Camera // 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( const camera = Camera.init(
Point3{ .x = -2, .y = 2, .z = 1 }, lookFrom,
Point3{ .x = 0, .y = 0, .z = -1 }, lookAt,
Vec3{ .x = 0, .y = 1, .z = 0 }, vup,
20.0, 20.0,
aspectRatio aspectRatio,
aperture,
distToFocus
); );
const window = sdl.c.SDL_CreateWindow( 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 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 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); const sample = rayColor(r, world, &prng.random, maxDepth);
pixelColor.* = pixelColor.*.add(sample); pixelColor.* = pixelColor.*.add(sample);