diff options
| author | nsfisis <nsfisis@gmail.com> | 2023-06-25 23:49:58 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2023-06-25 23:49:58 +0900 |
| commit | aca6892c9e84144190941f0bb3b3f6b8f0fdc566 (patch) | |
| tree | 57db4d1f1d27bddc494a991626b25ac2332e9748 | |
| parent | fb72e21e3d3896ac611145719e641ff774accb51 (diff) | |
| download | RayTracingInOneWeekend.zig-aca6892c9e84144190941f0bb3b3f6b8f0fdc566.tar.gz RayTracingInOneWeekend.zig-aca6892c9e84144190941f0bb3b3f6b8f0fdc566.tar.zst RayTracingInOneWeekend.zig-aca6892c9e84144190941f0bb3b3f6b8f0fdc566.zip | |
7.2
| -rw-r--r-- | src/main.zig | 32 | ||||
| -rw-r--r-- | src/rtw/material.zig | 30 |
2 files changed, 49 insertions, 13 deletions
diff --git a/src/main.zig b/src/main.zig index 4a667f9..70da3fc 100644 --- a/src/main.zig +++ b/src/main.zig @@ -116,24 +116,25 @@ const Camera = struct { } }; -fn rayColor(r: Ray, world: Hittable, rng: Random, depth: u32) Color { +fn rayColor(r: Ray, background: Color, world: Hittable, rng: Random, depth: u32) Color { var rec: HitRecord = undefined; if (depth == 0) { // If we've exceeded the ray bounce limit, no more ligth is gathered. return rgb(0.0, 0.0, 0.0); } - if (world.hit(r, 0.001, inf, &rec)) { - var scattered: Ray = undefined; - var attenuation: Color = undefined; - if (rec.material.scatter(r, rec, &attenuation, &scattered, rng)) { - return attenuation.mulV(rayColor(scattered, world, rng, depth - 1)); - } else { - return rgb(0.0, 0.0, 0.0); - } + if (!world.hit(r, 0.001, inf, &rec)) { + // If the ray hits nothing, return the background color. + return background; + } + + var scattered: Ray = undefined; + var attenuation: Color = undefined; + const emitted = rec.material.emitted(rec.u, rec.v, rec.p); + if (rec.material.scatter(r, rec, &attenuation, &scattered, rng)) { + return emitted.add(attenuation.mulV(rayColor(scattered, background, world, rng, depth - 1))); + } else { + return emitted; } - const unit_dir = r.dir.normalized(); - const s = 0.5 * (unit_dir.y + 1.0); - return rgb(1.0, 1.0, 1.0).mul(1.0 - s).add(rgb(0.5, 0.7, 1.0).mul(s)); } fn writeColor(out: anytype, c: Color, samples_per_pixel: u32) !void { @@ -280,25 +281,30 @@ pub fn main() !void { var lookAt: Point3 = undefined; var vFov: f64 = 40; var aperture: f64 = 0; + var background: Color = undefined; if (scene == 1) { world = try generateRandomScene(rng, allocator); + background = rgb(0.70, 0.80, 1.00); lookFrom = .{ .x = 13, .y = 2, .z = 3 }; lookAt = .{ .x = 0, .y = 0, .z = 0 }; vFov = 20.0; aperture = 0.1; } else if (scene == 2) { world = try generateTwoSpheres(rng, allocator); + background = rgb(0.70, 0.80, 1.00); lookFrom = .{ .x = 13, .y = 2, .z = 3 }; lookAt = .{ .x = 0, .y = 0, .z = 0 }; vFov = 20.0; } else if (scene == 3) { world = try generateTwoPerlinSpheres(rng, allocator); + background = rgb(0.70, 0.80, 1.00); lookFrom = .{ .x = 13, .y = 2, .z = 3 }; lookAt = .{ .x = 0, .y = 0, .z = 0 }; vFov = 20.0; } else if (scene == 4) { world = try generateEarthScene(allocator); + background = rgb(0.70, 0.80, 1.00); lookFrom = .{ .x = 13, .y = 2, .z = 3 }; lookAt = .{ .x = 0, .y = 0, .z = 0 }; vFov = 20.0; @@ -336,7 +342,7 @@ pub fn main() !void { const u = (@intToFloat(f64, i) + randomReal01(rng)) / (image_width - 1); const v = (@intToFloat(f64, j) + randomReal01(rng)) / (image_height - 1); const r = camera.getRay(rng, u, v); - pixelColor = pixelColor.add(rayColor(r, world, rng, max_depth)); + pixelColor = pixelColor.add(rayColor(r, background, world, rng, max_depth)); } try writeColor(stdout, pixelColor, samples_per_pixel); } diff --git a/src/rtw/material.zig b/src/rtw/material.zig index 87244ab..311e5af 100644 --- a/src/rtw/material.zig +++ b/src/rtw/material.zig @@ -19,18 +19,30 @@ const MaterialTag = enum { diffuse, metal, dielectric, + diffuse_light, }; pub const Material = union(MaterialTag) { diffuse: DiffuseMaterial, metal: MetalMaterial, dielectric: DielectricMaterial, + diffuse_light: DiffuseLightMaterial, pub fn scatter(mat: Material, r_in: Ray, record: HitRecord, attenuation: *Color, scattered: *Ray, rng: Random) bool { return switch (mat) { MaterialTag.diffuse => |diffuse_mat| diffuse_mat.scatter(r_in, record, attenuation, scattered, rng), MaterialTag.metal => |metal_mat| metal_mat.scatter(r_in, record, attenuation, scattered, rng), MaterialTag.dielectric => |dielectric_mat| dielectric_mat.scatter(r_in, record, attenuation, scattered, rng), + MaterialTag.diffuse_light => |diffuse_light_mat| diffuse_light_mat.scatter(r_in, record, attenuation, scattered, rng), + }; + } + + pub fn emitted(mat: Material, u: f64, v: f64, p: Vec3) Color { + return switch (mat) { + MaterialTag.diffuse => rgb(0, 0, 0), + MaterialTag.metal => rgb(0, 0, 0), + MaterialTag.dielectric => rgb(0, 0, 0), + MaterialTag.diffuse_light => |diffuse_light_mat| diffuse_light_mat.emitted(u, v, p), }; } }; @@ -88,6 +100,24 @@ pub const DielectricMaterial = struct { } }; +pub const DiffuseLightMaterial = struct { + emit: Texture, + + fn scatter(mat: DiffuseLightMaterial, r_in: Ray, record: HitRecord, attenuation: *Color, scattered: *Ray, rng: Random) bool { + _ = mat; + _ = r_in; + _ = record; + _ = attenuation; + _ = scattered; + _ = rng; + return false; + } + + fn emitted(mat: DiffuseLightMaterial, u: f64, v: f64, p: Vec3) Color { + return mat.emit.value(u, v, p); + } +}; + fn reflect(v: Vec3, n: Vec3) Vec3 { return v.sub(n.mul(2 * v.dot(n))); } |
