From d248e30d365d5e401d5cd372aa415fb2f9a39326 Mon Sep 17 00:00:00 2001 From: Nat Lasseter Date: Mon, 24 Jun 2024 22:12:44 +0100 Subject: Chapter 10 --- Makefile | 2 +- camera.go | 2 +- hittable.go | 3 +++ material.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ ray.go | 8 ++++++-- rtiaw.go | 11 +++++++++-- vec3.go | 9 +++++++++ 7 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 material.go diff --git a/Makefile b/Makefile index 7a62fa2..5a16559 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ out.ppm : rtiaw ./$< > $@ rtiaw: $(wildcard *.go) - go build + go build -o $@ $^ .phony: view clean diff --git a/camera.go b/camera.go index b42e9e1..f33d98a 100644 --- a/camera.go +++ b/camera.go @@ -74,7 +74,7 @@ func (cam Camera) GetRay(row uint, col uint) Ray { pixel_sample := cam.Pixel00. Add(cam.PDU.Mul(SplatVec3(float64(col) + offset.X))). Add(cam.PDV.Mul(SplatVec3(float64(row) + offset.Y))); - return Ray{cam.Centre, pixel_sample.Sub(cam.Centre)}; + return Ray{cam.Centre, pixel_sample.Sub(cam.Centre), true}; } func unit_square() Vec3 { diff --git a/hittable.go b/hittable.go index 5ab11cc..42599ab 100644 --- a/hittable.go +++ b/hittable.go @@ -11,6 +11,7 @@ type HitRecord struct { P Vec3 N Vec3 T float64 + Mat Material } func (rec *HitRecord) SetFaceNormal(r Ray, out_n Vec3) { @@ -32,6 +33,7 @@ type Hittable interface { type Sphere struct { Origin Vec3 Radius float64 + Mat Material } func (s Sphere) Hit(r Ray, ray_t Interval) (rec HitRecord) { @@ -58,6 +60,7 @@ func (s Sphere) Hit(r Ray, ray_t Interval) (rec HitRecord) { rec.P = r.At(rec.T); out_n := rec.P.Sub(s.Origin).Div(SplatVec3(s.Radius)); rec.SetFaceNormal(r, out_n); + rec.Mat = s.Mat; rec.Valid = true; return; } diff --git a/material.go b/material.go new file mode 100644 index 0000000..66ea256 --- /dev/null +++ b/material.go @@ -0,0 +1,44 @@ +package main + +//Material + +type Material interface { + Attenuation() Vec3 + Scatter(r Ray, hit HitRecord) Ray +} + +//Lambertian + +type Lambertian struct { + Albedo Vec3 +} + +func (l Lambertian) Attenuation() Vec3 { + return l.Albedo; +} + +func (l Lambertian) Scatter(r Ray, hit HitRecord) Ray { + scat_dir := hit.N.Add(RandomVec3OnUnitSphere()); + if scat_dir.NearZero() { + scat_dir = hit.N; + } + return Ray{hit.P, scat_dir, true}; +} + +//Metal + +type Metal struct { + Albedo Vec3 + Fuzz float64 +} + +func (m Metal) Attenuation() Vec3 { + return m.Albedo; +} + +func (m Metal) Scatter(r Ray, hit HitRecord) Ray { + refl := r.Direction.Reflect(hit.N).Unit(). + Add(SplatVec3(m.Fuzz).Mul(RandomVec3OnUnitSphere())); + valid := refl.Dot(hit.N) > 0; + return Ray{hit.P, refl, valid}; +} diff --git a/ray.go b/ray.go index 18c8a39..2d7f29c 100644 --- a/ray.go +++ b/ray.go @@ -7,6 +7,7 @@ import ( type Ray struct { Origin Vec3 Direction Vec3 + Valid bool } func (r Ray) At(t float64) Vec3 { @@ -20,8 +21,11 @@ func (r Ray) Colour(world Hittable, md uint) Vec3 { hit := world.Hit(r, Interval{0.001, maths.Inf(1)}) if hit.Valid { - dir := hit.N.Add(RandomVec3OnUnitSphere()); - return Ray{hit.P, dir}.Colour(world, md - 1).Div(SplatVec3(10)); + scat := hit.Mat.Scatter(r, hit); + if scat.Valid { + return scat.Colour(world, md - 1).Mul(hit.Mat.Attenuation()); + } + return SplatVec3(0); } unit_dir := r.Direction.Unit(); diff --git a/rtiaw.go b/rtiaw.go index 99bc31a..d95501d 100644 --- a/rtiaw.go +++ b/rtiaw.go @@ -9,9 +9,16 @@ import ( func main() { start := time.Now(); + mat_ground := Lambertian{Vec3{0.8, 0.8, 0}}; + mat_centre := Lambertian{Vec3{0.1, 0.2, 0.5}}; + mat_left := Metal{Vec3{0.8, 0.8, 0.8}, 0.3}; + mat_right := Metal{Vec3{0.8, 0.6, 0.2}, 1.0}; + var world Hittables; - world.Add(Sphere{Vec3{0, 0 , -1}, 0.5}); - world.Add(Sphere{Vec3{0, -100.5, -1}, 100 }); + world.Add(Sphere{Vec3{ 0, -100.5, -1 }, 100 , mat_ground}); + world.Add(Sphere{Vec3{ 0, 0 , -1.2}, 0.5, mat_centre}); + world.Add(Sphere{Vec3{-1.0, 0 , -1 }, 0.5, mat_left}); + world.Add(Sphere{Vec3{ 1.0, 0 , -1 }, 0.5, mat_right}); cam := NewCamera(400, 16.0/9.0, 100, 50); cam.Render(world); diff --git a/vec3.go b/vec3.go index bc16a07..a540b7c 100644 --- a/vec3.go +++ b/vec3.go @@ -37,6 +37,11 @@ func (v Vec3) Mag() float64 { return maths.Sqrt(v.MagSqr()); } +func (v Vec3) NearZero() bool { + s := 1e-8; + return v.X < s && v.Y < s && v.Z < s; +} + func (v Vec3) Unit() Vec3 { m := v.Mag(); return Vec3{v.X / m, v.Y / m, v.Z / m}; @@ -86,3 +91,7 @@ func RandomVec3OnUnitSphere() (v Vec3) { return; } + +func (v Vec3) Reflect(n Vec3) Vec3 { + return v.Sub(SplatVec3(2 * v.Dot(n)).Mul(n)); +} -- cgit v1.2.1