62 lines
1.7 KiB
Zig
62 lines
1.7 KiB
Zig
const std = @import("std");
|
|
const Random = std.rand.Random;
|
|
|
|
const vec3 = @import("vec3.zig");
|
|
const Color = @import("color.zig").Color;
|
|
const Ray = @import("ray.zig").Ray;
|
|
const HitRecord = @import("hittable.zig").HitRecord;
|
|
|
|
pub const MaterialType = enum {
|
|
lambertian,
|
|
metal,
|
|
};
|
|
|
|
pub const Lambertian = struct {
|
|
color: Color,
|
|
|
|
pub fn scatter(self: Lambertian, ray: Ray, hit: HitRecord, rng: *Random) ?ScatteredRay {
|
|
var scatterDirection = hit.normal.add(vec3.random_unit_vector(rng));
|
|
// Catch degenerate scatter direction
|
|
if (scatterDirection.nearZero()) {
|
|
scatterDirection = hit.normal;
|
|
}
|
|
return ScatteredRay{
|
|
.ray = Ray{ .origin = hit.p, .direction = scatterDirection},
|
|
.color = self.color,
|
|
};
|
|
}
|
|
};
|
|
|
|
pub const Metal = struct {
|
|
color: Color,
|
|
fuzz: f32,
|
|
|
|
pub fn scatter(self: Metal, ray: Ray, hit: HitRecord, rng: *Random) ?ScatteredRay {
|
|
const reflected = ray.direction.unit().reflect(hit.normal);
|
|
const scattered = Ray{ .origin = hit.p, .direction = reflected.add(vec3.random_in_unit_sphere(rng).mul_s(self.fuzz)) };
|
|
if (scattered.direction.dot(hit.normal) <= 0) {
|
|
return null;
|
|
}
|
|
return ScatteredRay{
|
|
.ray = scattered,
|
|
.color = self.color,
|
|
};
|
|
}
|
|
};
|
|
|
|
pub const ScatteredRay = struct {
|
|
ray: Ray,
|
|
color: Color,
|
|
};
|
|
|
|
pub const Material = union(MaterialType) {
|
|
lambertian: Lambertian,
|
|
metal: Metal,
|
|
};
|
|
|
|
pub fn scatter(ray: Ray, hit: HitRecord, rng: *Random) ?ScatteredRay {
|
|
return switch (hit.material) {
|
|
.lambertian => |m| m.scatter(ray, hit, rng),
|
|
.metal => |m| m.scatter(ray, hit, rng),
|
|
};
|
|
} |