aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2023-06-25 23:49:58 +0900
committernsfisis <nsfisis@gmail.com>2023-06-25 23:49:58 +0900
commitaca6892c9e84144190941f0bb3b3f6b8f0fdc566 (patch)
tree57db4d1f1d27bddc494a991626b25ac2332e9748
parentfb72e21e3d3896ac611145719e641ff774accb51 (diff)
downloadRayTracingInOneWeekend.zig-aca6892c9e84144190941f0bb3b3f6b8f0fdc566.tar.gz
RayTracingInOneWeekend.zig-aca6892c9e84144190941f0bb3b3f6b8f0fdc566.tar.zst
RayTracingInOneWeekend.zig-aca6892c9e84144190941f0bb3b3f6b8f0fdc566.zip
7.2
-rw-r--r--src/main.zig32
-rw-r--r--src/rtw/material.zig30
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)));
}