aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNat Lasseter <user@4574.co.uk>2024-06-24 23:46:18 +0100
committerNat Lasseter <user@4574.co.uk>2024-06-24 23:46:18 +0100
commite6ef8088e25750bca6ab61bda24fcb7e9e929ed1 (patch)
tree4caeb8e14f04024d1c3948cc03a18683f29912b6
parentc64284af4f5fd44360b88261a1c49a36f8bc7344 (diff)
Chapter 13
-rw-r--r--camera.go26
-rw-r--r--interval.go4
-rw-r--r--rtiaw.go3
-rw-r--r--vec3.go15
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));
}