-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
96 lines (83 loc) · 2.67 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
package main
import (
"fmt"
"image"
"image/color"
"image/png"
"math"
"os"
)
// Author: https://github.com/cishiv
// Inspired by https://github.com/ssloy/tinyraytracer
// Camera view angle
const fieldOfView = math.Pi / 3.0
// 'Window' dimensions (image dimensions since we're writing directly to file)
const width = 1024
const height = 768
// Sample materials
var ivory = NewMaterial(NewVec3(0.4, 0.4, 0.3), NewVec4(0.6, 0.3, 0.1, 0.0), 50, 1.0)
var redRubber = NewMaterial(NewVec3(0.3, 0.1, 0.1), NewVec4(0.9, 0.1, 0.1, 0.0), 10, 1.0)
var mirror = NewMaterial(NewVec3(1.0, 1.0, 1.0), NewVec4(0.0, 10.0, 0.8, 0.0), 1425, 1.0)
var glass = NewMaterial(NewVec3(0.6, 0.7, 0.8), NewVec4(0.0, 0.5, 0.1, 0.8), 125, 1.5)
func render(spheres []Sphere, lights []Light) {
// Construct the framebuffer
framebuffer := make([]Vec3, width*height)
origin := NewVec3(0, 0, 0)
// Fill the framebuffer
fmt.Println("Filling framebuffer")
for j := 0; j < height; j++ {
for i := 0; i < width; i++ {
// Big math (TODO: Figure this out)
x := (float64(i) + 0.5) - width/2.0
y := -(float64(j) + 0.5) + height/2.0
// TODO: We're not 3D yet
z := -float64(height) / (2.0 * math.Tan(fieldOfView/2.0))
direction := NewVec3(x, y, z).Normalize()
framebuffer[i+j*width] = CastRay(&origin, &direction, spheres, lights, 0)
}
}
fmt.Println("Framebuffer filled successfully")
// Save to file
img := image.NewRGBA(image.Rect(0, 0, width, height))
fmt.Println("saving framebuffer to file")
// Iterate over the framebuffer and fill the image based on the gradient corresponding to the vectors in the buffer
var max float64
for j := 0; j < height; j++ {
for i := 0; i < width; i++ {
v := framebuffer[i+j*width]
max = math.Max(v.x, math.Max(v.y, v.z))
if max > 1 {
v = v.MultiplyScalar((1.0 / max))
}
r, g, b := v.ConvertToRGB()
c := color.RGBA{r, g, b, 255}
img.Set(i, j, c)
}
}
// Write the file
out, err := os.Create("test.png")
if err != nil {
fmt.Println("error occurred creating file")
}
defer out.Close()
png.Encode(out, img)
}
func main() {
render(createSpheres(), createLights())
}
func createSpheres() []Sphere {
spheres := make([]Sphere, 0)
spheres = append(spheres, NewSphere(-3, 0, -16, 2, ivory))
spheres = append(spheres, NewSphere(-1.0, -1.5, -12, 2, glass))
spheres = append(spheres, NewSphere(1.5, -0.5, -18, 3, redRubber))
spheres = append(spheres, NewSphere(7, 5, -18, 4, mirror))
fmt.Println(spheres)
return spheres
}
func createLights() []Light {
lights := make([]Light, 0)
lights = append(lights, NewLight(-20, 20, 20, 4.5))
lights = append(lights, NewLight(20, -20, -20, 1.8))
lights = append(lights, NewLight(30, 20, 30, 1.7))
return lights
}