/
scene.go
103 lines (82 loc) · 2.15 KB
/
scene.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
package main
import (
"fmt"
mgl "github.com/go-gl/mathgl/mgl32"
"golang.org/x/mobile/gl"
)
type Light struct {
color mgl.Vec3
position mgl.Vec3
}
func (light *Light) MoveTo(position mgl.Vec3) {
light.position = position
}
type Drawable interface {
Draw(Camera)
Transform(*mgl.Mat4) mgl.Mat4
UseShader(Shader) (Shader, bool)
}
// TODO: node tree with transforms
type Node struct {
Shape
transform *mgl.Mat4
shader Shader
}
func (node *Node) Draw(camera Camera) {
node.Shape.Draw(node.shader, camera)
}
func (node *Node) UseShader(parent Shader) (Shader, bool) {
if node.shader == nil || node.shader == parent {
node.shader = parent
return parent, false
}
node.shader.Use()
return node.shader, true
}
func (node *Node) Transform(parent *mgl.Mat4) mgl.Mat4 {
return MultiMul(node.transform, parent)
}
func (node *Node) String() string {
return fmt.Sprintf("<Shape of %d vertices; transform: %v>", node.Len(), node.transform)
}
type Scene interface {
Add(interface{})
Draw(Camera)
String() string
}
func NewScene() Scene {
return &sliceScene{
nodes: []Drawable{},
}
}
type sliceScene struct {
nodes []Drawable
transform *mgl.Mat4
}
func (scene *sliceScene) String() string {
return fmt.Sprintf("%d nodes", len(scene.nodes))
}
func (scene *sliceScene) Add(item interface{}) {
scene.nodes = append(scene.nodes, item.(Drawable))
}
func (scene *sliceScene) Draw(camera Camera) {
// Setup MVP
projection, view, position := camera.Projection(), camera.View(), camera.Position()
var parentShader Shader
for _, node := range scene.nodes {
shader, changed := node.UseShader(parentShader)
if changed {
// TODO: Pre-load these into relevant shaders?
gl.UniformMatrix4fv(shader.Uniform("cameraPos"), position[:])
gl.UniformMatrix4fv(shader.Uniform("view"), view[:])
gl.UniformMatrix4fv(shader.Uniform("projection"), projection[:])
}
// TODO: Move these into node.Draw?
model := node.Transform(scene.transform)
normal := model.Mul4(view).Inv().Transpose()
// Camera space
gl.UniformMatrix4fv(shader.Uniform("model"), model[:])
gl.UniformMatrix4fv(shader.Uniform("normalMatrix"), normal[:])
node.Draw(camera)
}
}