3 | 3 |
"image"
|
4 | 4 |
"image/color"
|
5 | 5 |
"math"
|
|
6 |
"math/rand"
|
6 | 7 |
)
|
7 | 8 |
|
8 | |
func NewColor(r, g, b, a uint8) color.Color {
|
|
9 |
func NewColor(r, g, b, a uint8) color.NRGBA {
|
9 | 10 |
return color.NRGBA{R: r, G: g, B: b, A: a}
|
10 | 11 |
}
|
11 | 12 |
|
|
16 | 17 |
// scan to fill in the picture
|
17 | 18 |
U1, U2 *Vector
|
18 | 19 |
FDist float64
|
|
20 |
Sky color.NRGBA
|
|
21 |
Oversample int
|
19 | 22 |
}
|
20 | 23 |
|
21 | 24 |
func (s *Scene) DirectionAt(u, v float64) *Vector {
|
|
24 | 27 |
}
|
25 | 28 |
|
26 | 29 |
func (s *Scene) ColorAt(u, v float64) color.Color {
|
27 | |
ray := NewRay(s.Look.Origin, s.DirectionAt(u, v))
|
|
30 |
var r, g, b, n int32 = 0, 0, 0, 0
|
|
31 |
sr, sg, sb := s.Sky.R, s.Sky.G, s.Sky.B
|
28 | 32 |
|
29 | |
minDist := math.Inf(1)
|
30 | |
var minGeom *Primitive = nil
|
|
33 |
for i := 0; i < s.Oversample; i++ {
|
|
34 |
du := (rand.Float64() - 0.5) / 200
|
|
35 |
dv := (rand.Float64() - 0.5) / 200
|
|
36 |
ray := NewRay(s.Look.Origin, s.DirectionAt(u+du, v+dv))
|
31 | 37 |
|
32 | |
for _, geom := range s.Geom {
|
33 | |
i, d := geom.Intersect(ray)
|
34 | |
if i != nil && d < minDist {
|
35 | |
minDist = d
|
36 | |
minGeom = &geom
|
|
38 |
minDist := math.Inf(1)
|
|
39 |
var minGeom *Primitive = nil
|
|
40 |
|
|
41 |
for _, geom := range s.Geom {
|
|
42 |
i, d := geom.Intersect(ray)
|
|
43 |
if i != nil && d < minDist {
|
|
44 |
minDist = d
|
|
45 |
minGeom = &geom
|
|
46 |
}
|
37 | 47 |
}
|
|
48 |
|
|
49 |
if minGeom != nil {
|
|
50 |
r += 255
|
|
51 |
g += 255
|
|
52 |
b += 255
|
|
53 |
} else {
|
|
54 |
r += int32(sr)
|
|
55 |
g += int32(sg)
|
|
56 |
b += int32(sb)
|
|
57 |
}
|
|
58 |
n++
|
38 | 59 |
}
|
39 | |
|
40 | |
if minGeom != nil {
|
41 | |
return NewColor(255, 255, 255, 255)
|
42 | |
}
|
43 | |
return NewColor(0, 0, 0, 255)
|
|
60 |
return NewColor(uint8(r / n), uint8(g / n), uint8(b / n), 255)
|
44 | 61 |
}
|
45 | 62 |
|
46 | 63 |
func (s *Scene) SetColor(i, j int, u, v float64, img *image.NRGBA) {
|
47 | 64 |
img.Set(i, j, s.ColorAt(u, v))
|
48 | 65 |
}
|
|
66 |
|
|
67 |
func (s *Scene) Render(img *image.NRGBA) {
|
|
68 |
rect := img.Bounds()
|
|
69 |
w, h := float64(rect.Dx()), float64(rect.Dy())
|
|
70 |
i_max, j_max := rect.Dx(), rect.Dy()
|
|
71 |
for i := 0; i < i_max; i++ {
|
|
72 |
u := (float64(i) - w / 2.0) / (w / 2.0)
|
|
73 |
for j := 0; j < j_max; j++ {
|
|
74 |
// (h / w) term is needed to correct for nonunity aspect ratios
|
|
75 |
v := (float64(j) - h / 2.0) / (h / 2.0) * (h / w)
|
|
76 |
go s.SetColor(i, j, u, v, img)
|
|
77 |
}
|
|
78 |
}
|
|
79 |
}
|