this repo has no description
1const zm = @import("zmath");
2
3const hittable = @import("hittable.zig");
4const Ray = @import("ray.zig");
5const util = @import("util.zig");
6
7pub const Material = union(enum) {
8 lambertian: Lambertian,
9 metal: Metal,
10
11 pub fn lambertian(albedo: zm.Vec) Material {
12 return .{ .lambertian = .{ .albedo = albedo } };
13 }
14
15 pub fn metal(albedo: zm.Vec, fuzz: f32) Material {
16 return .{ .metal = .{ .albedo = albedo, .fuzz = if (fuzz < 1) fuzz else 1.0 } };
17 }
18
19 pub fn scatter(self: *Material, r: *Ray, rec: *hittable.HitRecord, attenuation: *zm.Vec) ?Ray {
20 return switch (self.*) {
21 .lambertian => |*lambert| lambert.scatter(rec, attenuation),
22 .metal => |*met| met.scatter(r, rec, attenuation),
23 };
24 }
25};
26
27pub const Lambertian = struct {
28 albedo: zm.Vec,
29
30 pub fn scatter(self: *Lambertian, rec: *hittable.HitRecord, attenuation: *zm.Vec) ?Ray {
31 var scatter_dir = rec.normal + util.randomUnitVec();
32
33 if (util.nearZero(scatter_dir)) scatter_dir = rec.normal;
34
35 attenuation.* = self.albedo;
36 return Ray.init(rec.p, scatter_dir);
37 }
38};
39
40pub const Metal = struct {
41 albedo: zm.Vec,
42 /// fuzz < 1
43 fuzz: f32,
44
45 pub fn scatter(self: *Metal, r: *Ray, rec: *hittable.HitRecord, attenuation: *zm.Vec) ?Ray {
46 const reflected = util.reflect(zm.normalize3(r.dir), rec.normal);
47 const scattered = Ray.init(rec.p, reflected + zm.f32x4s(self.fuzz) * util.randomUnitVec());
48 attenuation.* = self.albedo;
49 return if (zm.dot3(scattered.dir, rec.normal)[0] > 0) scattered else null;
50 }
51};