-
Notifications
You must be signed in to change notification settings - Fork 0
/
component.js
95 lines (81 loc) · 2.74 KB
/
component.js
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
var Component = require('kindred-component')
var GL_TRIANGLES = 4
var prevShader = null
var prevFrame = null
var prevGeom = null
module.exports = class RenderComponent extends Component('render') {
init (node, props) {
this.node = node
this.geometry = props.geometry
this.shader = props.shader
this.uniforms = props.uniforms || null
this.textures = props.textures || {}
this.drawStart = props.drawStart
this.drawCount = props.drawCount
this.zIndex = props.zIndex || 0
this.stopped = false
this.primitive = typeof props.primitive === 'number'
? props.primitive
: GL_TRIANGLES
}
stop () {
this.geometry = null
this.shader = null
this.node = null
this.stopped = true
}
draw (props) {
if (this.stopped) return
if (!this.node.data.visible) return
var shader = this.shader
var changedShader = false
var gl = props.gl
if (process.env.NODE_ENV !== 'production' && (!shader || !this.geometry)) {
throw new Error('kindred-renderer component needs both a .geometry and .shader to be supplied')
}
var uniforms = shader.uniforms
// Only switch shaders and upload common uniforms when necessary :)
// Frames are being counted to ensure that the state is "reset" at
// the start of a new frame.
if (shader !== prevShader || props.frame > prevFrame) {
shader.bind(gl)
uniforms.uFrame = props.frame
uniforms.uProj = props.proj
uniforms.uView = props.view
uniforms.uFog = props.fog
uniforms.uEye = props.eye
prevShader = shader
prevFrame = props.frame
changedShader = true
}
// Note: optimised previously to check if model/normal had changed
// in the hope of reducing draw calls, found it increased CPU significantly.
// Will need to test further, but will probably only be useful on normal
// matrices if anything.
uniforms.uModel = this.node.modelMatrix
uniforms.uNormal = this.node.normalMatrix
// Note: this could be optimised more by only rebinding textures
// when necessary. We could keep a "pool" of textures and just
// keep binding them to new indices only when required.
if (this.textures) {
var index = 0
for (var key in this.textures) {
var tex = this.textures[key]
if (typeof tex === 'number') {
uniforms[key] = tex
} else
if (tex) {
uniforms[key] = tex.bind(gl, index++)
}
}
}
if (this.uniforms !== null) {
this.uniforms(gl, this.node, uniforms)
}
if (changedShader || prevGeom !== this.geometry) {
this.geometry.bind(gl, shader.attributes)
prevGeom = this.geometry
}
this.geometry.draw(gl, this.primitive, this.drawStart, this.drawCount)
}
}