From e6ef8088e25750bca6ab61bda24fcb7e9e929ed1 Mon Sep 17 00:00:00 2001 From: Nat Lasseter Date: Mon, 24 Jun 2024 23:46:18 +0100 Subject: Chapter 13 --- camera.go | 26 +++++++++++++++++++++----- interval.go | 4 ---- rtiaw.go | 3 ++- vec3.go | 15 ++++++++++++++- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/camera.go b/camera.go index 66981aa..8ca0664 100644 --- a/camera.go +++ b/camera.go @@ -15,12 +15,16 @@ type Camera struct { Pixel00 Vec3 AntiAliasing uint MaxDepth uint + DOF float64 + DefDiskU Vec3 + DefDiskV Vec3 } func NewCamera(wi uint, ar float64, aa uint, md uint, vfov float64, lookfrom Vec3, - lookat Vec3, vup Vec3) (cam Camera) { + lookat Vec3, vup Vec3, + dof float64, fd float64) (cam Camera) { cam.ImageWidth = wi; cam.ImageHeight = uint(float64(cam.ImageWidth) / ar); if cam.ImageHeight < 1 { @@ -30,11 +34,11 @@ func NewCamera(wi uint, ar float64, cam.AntiAliasing = aa; cam.MaxDepth = md; cam.Centre = lookfrom; + cam.DOF = dof; - focal_length := lookfrom.Sub(lookat).Mag(); theta := vfov * maths.Pi / 180; h := maths.Tan(theta / 2) - viewport_height := 2.0 * h * focal_length; + viewport_height := 2.0 * h * fd; viewport_width := viewport_height * float64(cam.ImageWidth) / float64(cam.ImageHeight); @@ -50,12 +54,16 @@ func NewCamera(wi uint, ar float64, cam.PDV = viewport_v.Div(SplatVec3(float64(cam.ImageHeight))); viewport_upperleft := cam.Centre. - Sub(SplatVec3(focal_length).Mul(w)). + Sub(SplatVec3(fd).Mul(w)). Sub(viewport_u.Div(SplatVec3(2))). Sub(viewport_v.Div(SplatVec3(2))); cam.Pixel00 = viewport_upperleft. Add(cam.PDU.Add(cam.PDV).Div(SplatVec3(2))); + def_radius := fd * maths.Tan((cam.DOF / 2) * (maths.Pi / 180)); + cam.DefDiskU = SplatVec3(def_radius).Mul(u); + cam.DefDiskV = SplatVec3(def_radius).Mul(v); + return; } @@ -84,7 +92,15 @@ 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), true}; + origin := cam.Centre; + if cam.DOF > 0 { + p := RandomVec3OnUnitDisk(); + origin = cam.Centre. + Add(SplatVec3(p.X).Mul(cam.DefDiskU)). + Add(SplatVec3(p.Y).Mul(cam.DefDiskV)); + } + direction := pixel_sample.Sub(origin); + return Ray{origin, direction, true}; } func unit_square() Vec3 { diff --git a/interval.go b/interval.go index b7deb68..763939a 100644 --- a/interval.go +++ b/interval.go @@ -34,7 +34,3 @@ func (i Interval) Clamp(x float64) float64 { func (i Interval) Sample() float64 { return rand.Float64() * i.Size() + i.Min; } - -func (i Interval) RandomVec3() Vec3 { - return Vec3{i.Sample(), i.Sample(), i.Sample()}; -} diff --git a/rtiaw.go b/rtiaw.go index 25dd971..ab2c503 100644 --- a/rtiaw.go +++ b/rtiaw.go @@ -25,7 +25,8 @@ func main() { cam := NewCamera(400, 16.0/9.0, 100, 50, 20, Vec3{-2, 2, 1}, - Vec3{0, 0, -1}, Vec3{0, 1, 0}); + Vec3{0, 0, -1}, Vec3{0, 1, 0}, + 10.0, 3.4); cam.Render(world); dur := time.Since(start); diff --git a/vec3.go b/vec3.go index f590625..068ef6c 100644 --- a/vec3.go +++ b/vec3.go @@ -82,7 +82,7 @@ func RandomVec3OnUnitSphere() (v Vec3) { i := Interval{-1, 1} for true { - v = i.RandomVec3() + v = Vec3{i.Sample(), i.Sample(), i.Sample()}; if v.MagSqr() < 1 { v = v.Unit(); return; @@ -92,6 +92,19 @@ func RandomVec3OnUnitSphere() (v Vec3) { return; } +func RandomVec3OnUnitDisk() (v Vec3) { + i := Interval{-1, 1} + + for true { + v = Vec3{i.Sample(), i.Sample(), 0}; + if v.MagSqr() < 1 { + return; + } + } + + return; +} + func (v Vec3) Reflect(n Vec3) Vec3 { return v.Sub(SplatVec3(2 * v.Dot(n)).Mul(n)); } -- cgit v1.2.1