diff --git a/in_one_weekend/src/color.zig b/in_one_weekend/src/color.zig index d15dadd..a24ec8f 100644 --- a/in_one_weekend/src/color.zig +++ b/in_one_weekend/src/color.zig @@ -9,9 +9,13 @@ pub fn averageColor(pixelColor: *Color, samplesPerPixel: i32) Color { // const scale = 1.0 / @intToFloat(f32, samplesPerPixel); var scaledColor = pixelColor.*.div(@intToFloat(f32, samplesPerPixel)); + const r = math.sqrt(scaledColor.x); + const g = math.sqrt(scaledColor.y); + const b = math.sqrt(scaledColor.z); + return Color{ - .x = math.clamp(scaledColor.x, 0, 0.999), - .y = math.clamp(scaledColor.y, 0, 0.999), - .z = math.clamp(scaledColor.z, 0, 0.999), + .x = math.clamp(r, 0, 0.999), + .y = math.clamp(g, 0, 0.999), + .z = math.clamp(b, 0, 0.999), }; } \ No newline at end of file diff --git a/in_one_weekend/src/main.zig b/in_one_weekend/src/main.zig index 2277b18..c3f78ef 100644 --- a/in_one_weekend/src/main.zig +++ b/in_one_weekend/src/main.zig @@ -1,5 +1,6 @@ const std = @import("std"); const print = std.debug.print; +const Random = std.rand.Random; const sdl = @import("sdl.zig"); const vec3 = @import("vec3.zig"); const Vec3 = vec3.Vec3; @@ -33,9 +34,16 @@ fn hitSphere(center: Point3, radius: f32, ray: Ray) f32 { } } -fn rayColor(ray: Ray, world: World) Color { - if (world.hit(ray, 0, 99999)) |hit| { - return hit.normal.add(Vec3{ .x = 1, .y = 1, .z = 1}).div(2); +fn rayColor(ray: Ray, world: World, rng: *Random, depth: i32) Color { + // If we've exceeded the ray bounce limit, no more light is gathered. + if (depth <= 0) { + return Color{ .x = 0, .y = 0, .z = 0 }; + } + + if (world.hit(ray, 0.001, 99999)) |hit| { + const target = hit.p.add(hit.normal).add(vec3.random_in_unit_sphere(rng)); + const newRay = Ray{ .origin = hit.p, .direction = target.sub(hit.p)}; + return rayColor(newRay, world, rng, depth - 1).div(2); } const unitDirection = vec3.unitVector(ray.direction); const t = 0.5 * (unitDirection.y + 1.0); @@ -76,6 +84,7 @@ pub fn main() anyerror!void { const imageWidth = 600; const imageHeight = @floatToInt(usize, imageWidth / aspectRatio); const samplesPerPixel = 100; + const maxDepth = 5; // World const spheres = [_]Sphere{ @@ -143,7 +152,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 sample = rayColor(r, world); + const sample = rayColor(r, world, &prng.random, maxDepth); pixelColor.* = pixelColor.*.add(sample); const averageColor = color.averageColor(pixelColor, @intCast(i32, k)); diff --git a/in_one_weekend/src/vec3.zig b/in_one_weekend/src/vec3.zig index 8e0df49..4b81de6 100644 --- a/in_one_weekend/src/vec3.zig +++ b/in_one_weekend/src/vec3.zig @@ -1,4 +1,7 @@ -const math = @import("std").math; +const std = @import("std"); +const print = std.debug.print; +const math = std.math; +const Random = std.rand.Random; pub const Vec3 = packed struct { x: f32 = 0.0, @@ -66,6 +69,24 @@ pub fn unitVector(vec: Vec3) Vec3 { return vec.div(vec.length()); } +pub fn random(rng: *Random, min: f32, max: f32) Vec3 { + const range = max - min; + return Vec3{ + .x = rng.*.float(f32) * range + min, + .y = rng.*.float(f32) * range + min, + .z = rng.*.float(f32) * range + min, + }; +} + +pub fn random_in_unit_sphere(rng: *Random) Vec3 { + while (true) { + const v = random(rng, -1, 1); + if (v.length_squared() < 1) { + return v; + } + } +} + pub const Point3 = Vec3; const assert = @import("std").debug.assert;