57 lines
1.7 KiB
Zig
57 lines
1.7 KiB
Zig
const vec = @import("./vec.zig");
|
|
const Ray = @import("./ray.zig").Ray;
|
|
const HitRecord = @import("./hittable.zig").HitRecord;
|
|
|
|
const Vec3 = vec.Vec3;
|
|
const Color = vec.Color;
|
|
const random_unit_vector = vec.random_unit_vector;
|
|
|
|
pub const Material = union(enum) {
|
|
labertian: Labertian,
|
|
metal: Metal,
|
|
|
|
pub fn scatter(material: Material, r_in: Ray, rec: HitRecord) ?ScatterRec {
|
|
return switch (material) {
|
|
.labertian => |labertian| labertian.scatter(r_in, rec),
|
|
.metal => |metal| metal.scatter(r_in, rec),
|
|
};
|
|
}
|
|
};
|
|
|
|
pub const ScatterRec = struct { attenuation: Color, scattered: Ray };
|
|
|
|
pub const Labertian = struct {
|
|
albedo: Vec3,
|
|
pub fn scatter(labertian: Labertian, r_in: Ray, rec: HitRecord) ?ScatterRec {
|
|
_ = r_in;
|
|
var scatter_direction = rec.normal.add(random_unit_vector());
|
|
if (scatter_direction.near_zero()) {
|
|
scatter_direction = rec.normal;
|
|
}
|
|
return ScatterRec{
|
|
.scattered = Ray.init(rec.p, scatter_direction),
|
|
.attenuation = labertian.albedo,
|
|
};
|
|
}
|
|
};
|
|
|
|
pub const Metal = struct {
|
|
albedo: Vec3,
|
|
pub fn scatter(metal: Metal, r_in: Ray, rec: HitRecord) ?ScatterRec {
|
|
const reflected = reflect(r_in.direction().unit(), rec.normal);
|
|
const scattered = Ray.init(rec.p, reflected);
|
|
const attenuation = metal.albedo;
|
|
if (scattered.direction().dot(rec.normal) > 0) {
|
|
return ScatterRec{
|
|
.scattered = scattered,
|
|
.attenuation = attenuation,
|
|
};
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
fn reflect(v: Vec3, n: Vec3) Vec3 {
|
|
return v.sub(n.scale(v.dot(n) * 2));
|
|
}
|
|
};
|