zigrtiow: add material property to hittable.

This commit is contained in:
Bill Thiede 2022-08-06 08:06:53 -07:00
parent a2012e6742
commit d15a9e6c3e
5 changed files with 67 additions and 8 deletions

View File

@ -1,6 +1,8 @@
const vec = @import("./vec.zig");
const ray = @import("./ray.zig");
const Material = @import("./material.zig").Material;
const Sphere = @import("./sphere.zig").Sphere;
const HittableList = @import("./hittable_list.zig").HittableList;
@ -25,6 +27,7 @@ pub const HitRecord = struct {
normal: Vec3,
t: f32,
front_face: bool,
material: Material,
pub fn set_face_normal(hr: *HitRecord, r: Ray, outward_normal: Vec3) void {
hr.front_face = r.direction().dot(outward_normal) < 0;

View File

@ -6,27 +6,31 @@ const vec = @import("./vec.zig");
const sphere = @import("./sphere.zig");
const hittable = @import("./hittable.zig");
const hittable_list = @import("./hittable_list.zig");
const material = @import("./material.zig");
const Camera = camera.Camera;
const Color = vec.Color;
const Hittable = hittable.Hittable;
const HittableList = hittable_list.HittableList;
const Labertian = material.Labertian;
const Material = material.Material;
const Point3 = vec.Point3;
const Ray = ray.Ray;
const Sphere = sphere.Sphere;
const Vec3 = vec.Vec3;
const random_in_hemisphere = vec.random_in_hemisphere;
const info = std.log.info;
const random_in_hemisphere = vec.random_in_hemisphere;
const write_color = color.write_color;
fn ray_color(r: Ray, world: Hittable, depth: isize) Color {
// If we've exceeded the ray bounce limit, no more light is gathered.
if (depth <= 0) return Color.init(0, 0, 0);
var hit = world.hit(r, 0.0001, std.math.inf(f32));
if (hit) |rec| {
const target = rec.p.add(rec.normal.add(random_in_hemisphere(rec.normal)));
return ray_color(Ray.init(rec.p, target.sub(rec.p)), world, depth - 1).scale(0.5);
if (world.hit(r, 0.0001, std.math.inf(f32))) |hit_rec| {
if (hit_rec.material.scatter(r, hit_rec)) |scatter_rec| {
return scatter_rec.attenuation.mul(ray_color(scatter_rec.scattered, world, depth - 1));
}
return Color.init(0, 0, 0);
}
var unit_direction = r.direction().unit();
const t = 0.5 * (unit_direction.y() + 1);
@ -43,8 +47,12 @@ pub fn main() anyerror!void {
// World
var tmp_world = HittableList.init();
try tmp_world.add(Hittable{ .sphere = Sphere.init(Point3.init(0, 0, -1), 0.5) });
try tmp_world.add(Hittable{ .sphere = Sphere.init(Point3.init(0, -100.5, -1), 100) });
const material_ground = Material{ .labertian = Labertian{ .albedo = Color.init(0.8, 0.8, 0.0) } };
const material_center = Material{ .labertian = Labertian{ .albedo = Color.init(0.7, 0.3, 0.3) } };
try tmp_world.add(Hittable{ .sphere = Sphere.init(Point3.init(0, -100.5, -1), 100, material_ground) });
try tmp_world.add(Hittable{ .sphere = Sphere.init(Point3.init(0, 0, -1), 0.5, material_center) });
const world = Hittable{ .hittable_list = tmp_world };
// Camera

34
zigrtiow/src/material.zig Normal file
View File

@ -0,0 +1,34 @@
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,
pub fn scatter(material: Material, r_in: Ray, rec: HitRecord) ?ScatterRec {
return switch (material) {
.labertian => |labertian| labertian.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,
};
}
};

View File

@ -2,6 +2,8 @@ const vec = @import("./vec.zig");
const ray = @import("./ray.zig");
const hittable = @import("./hittable.zig");
const Material = @import("./material.zig").Material;
const Vec3 = vec.Vec3;
const Point3 = vec.Point3;
const Ray = ray.Ray;
@ -10,11 +12,13 @@ const HitRecord = hittable.HitRecord;
pub const Sphere = struct {
center: Point3,
radius: f32,
material: Material,
pub fn init(center: Point3, radius: f32) Sphere {
pub fn init(center: Point3, radius: f32, material: Material) Sphere {
return Sphere{
.center = center,
.radius = radius,
.material = material,
};
}
pub fn hit(sphere: Sphere, r: Ray, t_min: f32, t_max: f32) ?HitRecord {
@ -44,6 +48,7 @@ pub const Sphere = struct {
.p = p,
.normal = Vec3.init(0, 0, 0),
.front_face = false,
.material = sphere.material,
};
hr.set_face_normal(r, outward_normal);
return hr;

View File

@ -34,6 +34,9 @@ pub const Vec3 = struct {
pub fn sub(lhs: Vec3, rhs: Vec3) Vec3 {
return Vec3{ .v = lhs.v - rhs.v };
}
pub fn mul(lhs: Vec3, rhs: Vec3) Vec3 {
return Vec3{ .v = lhs.v * rhs.v };
}
pub fn scale(vec: Vec3, t: f32) Vec3 {
return Vec3{ .v = vec.v * @splat(3, t) };
}
@ -52,6 +55,12 @@ pub const Vec3 = struct {
rand.float(f32) * 2 - 1,
);
}
pub fn near_zero(vec: Vec3) bool {
// Return true if the vector is close to zero in all dimensions.
const s = 1e-8;
const e = vec.v;
return (@fabs(e[0]) < s) and (@fabs(e[1]) < s) and (@fabs(e[2]) < s);
}
};
pub fn random_in_unit_sphere() Vec3 {