1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
package main
import (
"fmt"
maths "math"
"os"
)
type Camera struct {
ImageWidth uint
ImageHeight uint
Centre Vec3
PDU Vec3
PDV Vec3
Pixel00 Vec3
AntiAliasing uint
MaxDepth uint
}
func NewCamera(wi uint, ar float64,
aa uint, md uint,
vfov float64, lookfrom Vec3,
lookat Vec3, vup Vec3) (cam Camera) {
cam.ImageWidth = wi;
cam.ImageHeight = uint(float64(cam.ImageWidth) / ar);
if cam.ImageHeight < 1 {
cam.ImageHeight = 1;
}
cam.AntiAliasing = aa;
cam.MaxDepth = md;
cam.Centre = lookfrom;
focal_length := lookfrom.Sub(lookat).Mag();
theta := vfov * maths.Pi / 180;
h := maths.Tan(theta / 2)
viewport_height := 2.0 * h * focal_length;
viewport_width := viewport_height *
float64(cam.ImageWidth) /
float64(cam.ImageHeight);
w := lookfrom.Sub(lookat).Unit();
u := vup.Cross(w).Unit();
v := w.Cross(u);
viewport_u := SplatVec3(viewport_width).Mul(u);
viewport_v := SplatVec3(viewport_height).Mul(v.Neg());
cam.PDU = viewport_u.Div(SplatVec3(float64(cam.ImageWidth)));
cam.PDV = viewport_v.Div(SplatVec3(float64(cam.ImageHeight)));
viewport_upperleft := cam.Centre.
Sub(SplatVec3(focal_length).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)));
return;
}
func (cam Camera) Render(world Hittable) {
fmt.Printf("P3\n%d %d\n255\n", cam.ImageWidth, cam.ImageHeight);
for row := uint(0); row < cam.ImageHeight; row++ {
fmt.Fprintf(os.Stderr,
"[GScanlines remaining: %3d...",
(cam.ImageHeight - row));
for col := uint(0); col < cam.ImageWidth; col++ {
pixel_colour := SplatVec3(0);
for i := uint(0); i < cam.AntiAliasing; i++ {
r := cam.GetRay(row, col);
pixel_colour = pixel_colour.Add(r.Colour(world, cam.MaxDepth));
}
pixel_colour = pixel_colour.
Div(SplatVec3(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(SplatVec3(float64(col) + offset.X))).
Add(cam.PDV.Mul(SplatVec3(float64(row) + offset.Y)));
return Ray{cam.Centre, pixel_sample.Sub(cam.Centre), true};
}
func unit_square() Vec3 {
i := Interval{-0.5, 0.5};
return Vec3{i.Sample(), i.Sample(), 0};
}
|