From 3deef4d969dd50ddf540b80fe43ef16af5c17169 Mon Sep 17 00:00:00 2001 From: Nat Lasseter Date: Mon, 24 Jun 2024 22:51:51 +0100 Subject: Chapter 11 --- material.go | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) (limited to 'material.go') diff --git a/material.go b/material.go index 66ea256..62a0467 100644 --- a/material.go +++ b/material.go @@ -1,5 +1,9 @@ package main +import ( + maths "math" +) + //Material type Material interface { @@ -7,7 +11,7 @@ type Material interface { Scatter(r Ray, hit HitRecord) Ray } -//Lambertian +//Lambertian < Material type Lambertian struct { Albedo Vec3 @@ -25,7 +29,7 @@ func (l Lambertian) Scatter(r Ray, hit HitRecord) Ray { return Ray{hit.P, scat_dir, true}; } -//Metal +//Metal < Material type Metal struct { Albedo Vec3 @@ -42,3 +46,41 @@ func (m Metal) Scatter(r Ray, hit HitRecord) Ray { valid := refl.Dot(hit.N) > 0; return Ray{hit.P, refl, valid}; } + +//Dielectric < Material + +type Dielectric struct { + RefractionIndex float64 +} + +func (d Dielectric) Attenuation() Vec3 { + return SplatVec3(1); +} + +func (d Dielectric) Scatter(r Ray, hit HitRecord) Ray { + ri := d.RefractionIndex; + if hit.F { + ri = 1.0 / ri; + } + + unit_dir := r.Direction.Unit(); + cos_theta := maths.Min(unit_dir.Neg().Dot(hit.N), 1.0); + sin_theta := maths.Sqrt(1.0 - maths.Pow(cos_theta, 2)); + + cannot_refract := ri * sin_theta > 1.0; + + var dir Vec3; + if cannot_refract || schlick_reflect(cos_theta, ri) { + dir = unit_dir.Reflect(hit.N); + } else { + dir = unit_dir.Refract(hit.N, ri); + } + + return Ray{hit.P, dir, true}; +} + +func schlick_reflect(cos_theta float64, ri float64) bool { + r0 := maths.Pow((1 - ri) / (1 + ri), 2); + approx := r0 + (1 - r0) * maths.Pow(1 - cos_theta, 5); + return approx > Interval{0, 1}.Sample(); +} -- cgit v1.2.1