From 4a478b08a09c6b69683651ae2928b350df09fbc2 Mon Sep 17 00:00:00 2001 From: Fabien Freling Date: Thu, 27 May 2021 22:03:28 +0200 Subject: [PATCH] add total internal reflection --- in_one_weekend/src/main.zig | 4 ++-- in_one_weekend/src/material.zig | 11 +++++++++-- in_one_weekend/src/vec3.zig | 14 +++++++------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/in_one_weekend/src/main.zig b/in_one_weekend/src/main.zig index ecf6152..c9378b1 100644 --- a/in_one_weekend/src/main.zig +++ b/in_one_weekend/src/main.zig @@ -97,8 +97,8 @@ pub fn main() anyerror!void { } }; const materialCenter = Material{ - .dielectric = material.Dielectric{ - .refraction_index = 1.5, + .lambertian = material.Lambertian{ + .color = Color{ .x = 0.1, .y = 0.2, .z = 0.5 }, } }; const materialLeft = Material{ diff --git a/in_one_weekend/src/material.zig b/in_one_weekend/src/material.zig index 0396294..33df95e 100644 --- a/in_one_weekend/src/material.zig +++ b/in_one_weekend/src/material.zig @@ -1,5 +1,6 @@ const std = @import("std"); const Random = std.rand.Random; +const math = std.math; const vec3 = @import("vec3.zig"); const Color = @import("color.zig").Color; @@ -52,9 +53,15 @@ pub const Dielectric = struct { const attenuation = Color{ .x = 1.0, .y = 1.0, .z = 1.0 }; const refraction_ratio = if (hit.front_face) 1.0 / self.refraction_index else self.refraction_index; const unit_direction = ray.direction.unit(); - const refracted = vec3.refract(unit_direction, hit.normal, refraction_ratio); + + const cos_theta = math.min(unit_direction.mul_s(-1).dot(hit.normal), 1.0); + const sin_theta = math.sqrt(1.0 - cos_theta * cos_theta); + + const cant_refract = refraction_ratio * sin_theta > 1.0; + const direction = if (cant_refract) unit_direction.reflect(hit.normal) + else unit_direction.refract(hit.normal, refraction_ratio); return ScatteredRay{ - .ray = Ray{ .origin = hit.p, .direction = refracted}, + .ray = Ray{ .origin = hit.p, .direction = direction}, .color = attenuation, }; } diff --git a/in_one_weekend/src/vec3.zig b/in_one_weekend/src/vec3.zig index 0ada129..8b45c40 100644 --- a/in_one_weekend/src/vec3.zig +++ b/in_one_weekend/src/vec3.zig @@ -82,6 +82,13 @@ pub const Vec3 = packed struct { pub fn reflect(self: Vec3, n: Vec3) Vec3 { return self.sub(n.mul_s(self.dot(n) * 2)); } + + pub fn refract(self: Vec3, n: Vec3, etai_over_etat: f32) Vec3 { + const cos_theta = math.min(self.mul_s(-1).dot(n), 1.0); + const r_out_perp = self.add(n.mul_s(cos_theta)).mul_s(etai_over_etat); + const r_out_parallel = n.mul_s(-math.sqrt(math.absFloat(1.0 - r_out_perp.length_squared()))); + return r_out_perp.add(r_out_parallel); + } }; pub fn random(rng: *Random, min: f32, max: f32) Vec3 { @@ -116,13 +123,6 @@ pub fn random_in_hemisphere(rng: *Random, normal: Vec3) Vec3 { } } -pub fn refract(uv: Vec3, n: Vec3, etai_over_etat: f32) Vec3 { - const cos_theta = math.min(uv.mul_s(-1).dot(n), 1.0); - const r_out_perp = uv.add(n.mul_s(cos_theta)).mul_s(etai_over_etat); - const r_out_parallel = n.mul_s(-math.sqrt(math.absFloat(1.0 - r_out_perp.length_squared()))); - return r_out_perp.add(r_out_parallel); -} - pub const Point3 = Vec3; const assert = @import("std").debug.assert;