From 2f025ebfc6c9e3146ef1c356f99045edc203c9ee Mon Sep 17 00:00:00 2001 From: Nat Lasseter Date: Mon, 24 Jun 2024 16:50:36 +0100 Subject: Chapter 8 --- camera.go | 30 +++++++++++++++++++++++------- interval.go | 18 ++++++++++++++++++ rtiaw.go | 2 +- vec3.go | 8 +++++--- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/camera.go b/camera.go index e460cc0..569d385 100644 --- a/camera.go +++ b/camera.go @@ -12,15 +12,18 @@ type Camera struct { PDU Vec3 PDV Vec3 Pixel00 Vec3 + AntiAliasing uint } -func NewCamera(w uint, ar float64) (cam Camera) { +func NewCamera(w uint, ar float64, aa uint) (cam Camera) { cam.ImageWidth = w; cam.ImageHeight = uint(float64(cam.ImageWidth) / ar); if cam.ImageHeight < 1 { cam.ImageHeight = 1; } + cam.AntiAliasing = aa; + focal_length := 1.0; viewport_height := 2.0; viewport_width := viewport_height * @@ -51,14 +54,27 @@ func (cam Camera) Render(world Hittable) { "Scanlines remaining: %3d...", (cam.ImageHeight - row)); for col := uint(0); col < cam.ImageWidth; col++ { - pixel_centre := cam.Pixel00. - Add(cam.PDU.Mul(Splat(float64(col)))). - Add(cam.PDV.Mul(Splat(float64(row)))); - ray_direction := pixel_centre.Sub(cam.Centre); - ray := Ray{cam.Centre, ray_direction} - pixel_colour := ray.Colour(world); + pixel_colour := Splat(0); + for i := uint(0); i < cam.AntiAliasing; i++ { + r := cam.GetRay(row, col); + pixel_colour = pixel_colour.Add(r.Colour(world)); + } + pixel_colour = pixel_colour.Div(Splat(float64(cam.AntiAliasing))); fmt.Printf("%s ", pixel_colour.ToPPM()); } fmt.Printf("\n"); } } + +func (cam Camera) GetRay(row uint, col uint) Ray { + offset := unit_square(); + pixel_sample := cam.Pixel00. + Add(cam.PDU.Mul(Splat(float64(col) + offset.X))). + Add(cam.PDV.Mul(Splat(float64(row) + offset.Y))); + return Ray{cam.Centre, pixel_sample.Sub(cam.Centre)}; +} + +func unit_square() Vec3 { + i := Interval{-0.5, 0.5}; + return Vec3{i.Sample(), i.Sample(), 0}; +} diff --git a/interval.go b/interval.go index 5f44f51..763939a 100644 --- a/interval.go +++ b/interval.go @@ -1,5 +1,9 @@ package main +import ( + "math/rand" +) + type Interval struct { Min float64 Max float64 @@ -16,3 +20,17 @@ func (i Interval) Include(x float64) bool { func (i Interval) Surround(x float64) bool { return i.Min < x && x < i.Max; } + +func (i Interval) Clamp(x float64) float64 { + if x < i.Min { + return i.Min; + } + if x > i.Max { + return i.Max; + } + return x; +} + +func (i Interval) Sample() float64 { + return rand.Float64() * i.Size() + i.Min; +} diff --git a/rtiaw.go b/rtiaw.go index 03cee09..ec5975e 100644 --- a/rtiaw.go +++ b/rtiaw.go @@ -13,7 +13,7 @@ func main() { world.Add(Sphere{Vec3{0, 0 , -1}, 0.5}); world.Add(Sphere{Vec3{0, -100.5, -1}, 100 }); - cam := NewCamera(400, 16.0/9.0); + cam := NewCamera(400, 16.0/9.0, 100); cam.Render(world); dur := time.Since(start); diff --git a/vec3.go b/vec3.go index 65d14e5..4212b46 100644 --- a/vec3.go +++ b/vec3.go @@ -53,9 +53,11 @@ func (v Vec3) Cross(w Vec3) Vec3 { } func (v Vec3) ToPPM() string { - r := uint8(255.999 * v.X); - g := uint8(255.999 * v.Y); - b := uint8(255.999 * v.Z); + i := Interval{0, 0.999}; + + r := uint8(256 * i.Clamp(v.X)); + g := uint8(256 * i.Clamp(v.Y)); + b := uint8(256 * i.Clamp(v.Z)); return fmt.Sprintf("%3d %3d %3d", r, g, b); } -- cgit v1.2.1