/
main.go
125 lines (102 loc) · 2.48 KB
/
main.go
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package main
import (
"flag"
"image"
"image/color"
"image/png"
"os"
"runtime"
"runtime/pprof"
"sync"
)
var (
ppi = flag.Int("ppi", 16, "points per image")
ppp = flag.Int("ppp", 8, "pixels per point")
spp = flag.Int("spp", 4, "samples per pixel")
oct = flag.Int("oct", 3, "octaves of noise")
output = flag.String("o", "render.png", "output file")
cpuprof = flag.String("cpuprof", "", "write cpu profile to file")
basex = flag.Float64("x", 0, "base X coordinate")
basey = flag.Float64("y", 0, "base Y coordinate")
basez = flag.Float64("z", -10, "base Z coordinate")
)
const (
epsilon = 0.01
farZ = 200
)
func Pixel(x, y int, img *image.RGBA64, wg *sync.WaitGroup) {
var r, g, b, a uint64
for i := 0; i < *spp; i++ {
for j := 0; j < *spp; j++ {
X := (float64(x)+float64(i)/float64(*spp))/float64(*ppp) - float64(*ppi)/2
Y := float64(*ppi)/2 - (float64(y)+float64(j)/float64(*spp))/float64(*ppp)
c := Ray(X+*basex, Y+*basey, *basez,
X/float64(*ppi)*epsilon,
Y/float64(*ppi)*epsilon,
epsilon,
farZ)
r += uint64(c.R)
g += uint64(c.G)
b += uint64(c.B)
a += uint64(c.A)
}
}
img.SetRGBA64(x, y, color.RGBA64{
uint16(r / uint64(*spp) / uint64(*spp)),
uint16(g / uint64(*spp) / uint64(*spp)),
uint16(b / uint64(*spp) / uint64(*spp)),
uint16(a / uint64(*spp) / uint64(*spp)),
})
wg.Done()
}
func Worker(ch <-chan [2]int, img *image.RGBA64, wg *sync.WaitGroup) {
for p := range ch {
Pixel(p[0], p[1], img, wg)
}
}
func main() {
var cpus *int
if runtime.GOMAXPROCS(0) == 1 {
cpus = flag.Int("cpus", runtime.NumCPU(), "the number of processor cores to use at any given time")
} else {
cpus = flag.Int("cpus", runtime.GOMAXPROCS(0), "the number of processor cores to use at any given time")
}
flag.Parse()
if *cpuprof != "" {
f, err := os.Create(*cpuprof)
if err != nil {
panic(err)
}
defer f.Close()
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
runtime.GOMAXPROCS(*cpus)
noise0 = NewNoiseGen(0, *oct)
noise1 = NewNoiseGen(1, *oct)
noise2 = NewNoiseGen(2, *oct)
var wg sync.WaitGroup
dim := *ppi * *ppp
img := image.NewRGBA64(image.Rect(0, 0, dim, dim))
ch := make(chan [2]int, 16)
for i := 0; i < *cpus; i++ {
go Worker(ch, img, &wg)
}
for x := 0; x < dim; x++ {
for y := 0; y < dim; y++ {
wg.Add(1)
ch <- [2]int{x, y}
}
}
close(ch)
wg.Wait()
f, err := os.Create(*output)
if err != nil {
panic(err)
}
defer f.Close()
err = png.Encode(f, img)
if err != nil {
panic(err)
}
}