implement Material as tagged union
This commit is contained in:
parent
bc3fb54991
commit
c842fcf713
|
@ -14,8 +14,6 @@ const World = @import("world.zig").World;
|
||||||
const Camera = @import("camera.zig").Camera;
|
const Camera = @import("camera.zig").Camera;
|
||||||
const material = @import("material.zig");
|
const material = @import("material.zig");
|
||||||
const Material = material.Material;
|
const Material = material.Material;
|
||||||
const MaterialType = material.MaterialType;
|
|
||||||
const scatter = @import("material.zig").scatter;
|
|
||||||
|
|
||||||
// From: https://github.com/Nelarius/weekend-raytracer-zig/blob/master/src/main.zig
|
// From: https://github.com/Nelarius/weekend-raytracer-zig/blob/master/src/main.zig
|
||||||
// See https://github.com/zig-lang/zig/issues/565
|
// See https://github.com/zig-lang/zig/issues/565
|
||||||
|
@ -46,7 +44,7 @@ fn rayColor(ray: Ray, world: World, rng: *Random, depth: i32) Color {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (world.hit(ray, 0.001, 99999)) |hit| {
|
if (world.hit(ray, 0.001, 99999)) |hit| {
|
||||||
if (scatter(ray, hit, rng)) |sRay| {
|
if (material.scatter(ray, hit, rng)) |sRay| {
|
||||||
return sRay.color.mul(rayColor(sRay.ray, world, rng, depth - 1));
|
return sRay.color.mul(rayColor(sRay.ray, world, rng, depth - 1));
|
||||||
}
|
}
|
||||||
return Color{ .x = 0, .y = 0, .z = 0 };
|
return Color{ .x = 0, .y = 0, .z = 0 };
|
||||||
|
@ -94,20 +92,24 @@ pub fn main() anyerror!void {
|
||||||
|
|
||||||
// World
|
// World
|
||||||
const materialGround = Material{
|
const materialGround = Material{
|
||||||
.materialType = .Lambertian,
|
.lambertian = material.Lambertian{
|
||||||
.color = Color{ .x = 0.8, .y = 0.8, .z = 0.0 },
|
.color = Color{ .x = 0.8, .y = 0.8, .z = 0.0 }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const materialCenter = Material{
|
const materialCenter = Material{
|
||||||
.materialType = .Lambertian,
|
.lambertian = material.Lambertian{
|
||||||
.color = Color{ .x = 0.7, .y = 0.3, .z = 0.3 },
|
.color = Color{ .x = 0.7, .y = 0.3, .z = 0.3 }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const materialLeft = Material{
|
const materialLeft = Material{
|
||||||
.materialType = .Metal,
|
.metal = material.Metal{
|
||||||
.color = Color{ .x = 0.8, .y = 0.8, .z = 0.8 },
|
.color = Color{ .x = 0.8, .y = 0.8, .z = 0.8 }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const materialRight = Material{
|
const materialRight = Material{
|
||||||
.materialType = .Metal,
|
.metal = material.Metal{
|
||||||
.color = Color{ .x = 0.8, .y = 0.6, .z = 0.2 },
|
.color = Color{ .x = 0.8, .y = 0.6, .z = 0.2 }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const spheres = [_]Sphere{
|
const spheres = [_]Sphere{
|
||||||
|
|
|
@ -7,13 +7,41 @@ const Ray = @import("ray.zig").Ray;
|
||||||
const HitRecord = @import("hittable.zig").HitRecord;
|
const HitRecord = @import("hittable.zig").HitRecord;
|
||||||
|
|
||||||
pub const MaterialType = enum {
|
pub const MaterialType = enum {
|
||||||
Lambertian,
|
lambertian,
|
||||||
Metal,
|
metal,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Material = struct {
|
pub const Lambertian = struct {
|
||||||
materialType: MaterialType,
|
|
||||||
color: Color,
|
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,
|
||||||
|
// fuzzy: 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 };
|
||||||
|
if (scattered.direction.dot(hit.normal) <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ScatteredRay{
|
||||||
|
.ray = scattered,
|
||||||
|
.color = self.color,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ScatteredRay = struct {
|
pub const ScatteredRay = struct {
|
||||||
|
@ -21,35 +49,14 @@ pub const ScatteredRay = struct {
|
||||||
color: Color,
|
color: Color,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Material = union(MaterialType) {
|
||||||
|
lambertian: Lambertian,
|
||||||
|
metal: Metal,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn scatter(ray: Ray, hit: HitRecord, rng: *Random) ?ScatteredRay {
|
pub fn scatter(ray: Ray, hit: HitRecord, rng: *Random) ?ScatteredRay {
|
||||||
const scatteredDirection = switch (hit.material.materialType) {
|
return switch (hit.material) {
|
||||||
|
.lambertian => |m| m.scatter(ray, hit, rng),
|
||||||
.Lambertian => blk: {
|
.metal => |m| m.scatter(ray, hit, rng),
|
||||||
var scatterDirection = hit.normal.add(vec3.random_unit_vector(rng));
|
|
||||||
// Catch degenerate scatter direction
|
|
||||||
if (scatterDirection.nearZero()) {
|
|
||||||
scatterDirection = hit.normal;
|
|
||||||
}
|
|
||||||
break :blk scatterDirection;
|
|
||||||
},
|
|
||||||
|
|
||||||
.Metal => blk: {
|
|
||||||
const reflected = ray.direction.unit().reflect(hit.normal);
|
|
||||||
const scattered = Ray{ .origin = hit.p, .direction = reflected };
|
|
||||||
if (scattered.direction.dot(hit.normal) <= 0) {
|
|
||||||
break :blk null;
|
|
||||||
}
|
|
||||||
break :blk scattered.direction;
|
|
||||||
},
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (scatteredDirection) |dir| {
|
|
||||||
return ScatteredRay{
|
|
||||||
.ray = Ray{ .origin = hit.p, .direction = dir},
|
|
||||||
.color = hit.material.color,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue