forked from regl-project/regl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
instance-mesh.js
145 lines (118 loc) Β· 3.28 KB
/
instance-mesh.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
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
tags: instancing, basic
<p> In this example, it is shown how you can draw a bunch of bunny meshes using the
instancing feature of regl. </p>
*/
const mat4 = require('gl-mat4')
const bunny = require('bunny')
const fit = require('canvas-fit')
const normals = require('angle-normals')
const canvas = document.body.appendChild(document.createElement('canvas'))
const regl = require('../regl')({canvas: canvas, extensions: ['angle_instanced_arrays']})
const camera = require('canvas-orbit-camera')(canvas)
window.addEventListener('resize', fit(canvas), false)
// configure initial camera view.
camera.rotate([0.0, 0.0], [0.0, -0.4])
camera.zoom(70.0)
var N = 15 // N bunnies on the width, N bunnies on the height.
var angle = []
for (var i = 0; i < N * N; i++) {
// generate random initial angle.
angle[i] = Math.random() * (2 * Math.PI)
}
// This buffer stores the angles of all
// the instanced bunnies.
const angleBuffer = regl.buffer({
length: angle.length * 4,
type: 'float',
usage: 'dynamic'
})
const drawBunnies = regl({
frag: `
precision mediump float;
varying vec3 vNormal;
varying vec3 vColor;
void main () {
vec3 color = vColor;
vec3 ambient = vec3(0.3) * color;
vec3 lightDir = vec3(0.39, 0.87, 0.29);
vec3 diffuse = vec3(0.7) * color * clamp(dot(vNormal, lightDir) , 0.0, 1.0 );
gl_FragColor = vec4(ambient + diffuse, 1.0);
}`,
vert: `
precision mediump float;
attribute vec3 position;
attribute vec3 normal;
// These three are instanced attributes.
attribute vec3 offset;
attribute vec3 color;
attribute float angle;
uniform mat4 proj;
uniform mat4 model;
uniform mat4 view;
varying vec3 vNormal;
varying vec3 vColor;
void main () {
vNormal = normal;
vColor = color;
gl_Position = proj * view * model * vec4(
+cos(angle) * position.x + position.z * sin(angle) + offset.x,
position.y + offset.y,
-sin(angle) * position.x + position.z * cos(angle) + offset.z,
1.0);
}`,
attributes: {
position: bunny.positions,
normal: normals(bunny.cells, bunny.positions),
offset: {
buffer: regl.buffer(
Array(N * N).fill().map((_, i) => {
var x = (-1 + 2 * Math.floor(i / N) / N) * 120
var z = (-1 + 2 * (i % N) / N) * 120
return [x, 0.0, z]
})),
divisor: 1
},
color: {
buffer: regl.buffer(
Array(N * N).fill().map((_, i) => {
var x = Math.floor(i / N) / (N - 1)
var z = (i % N) / (N - 1)
return [
x * z * 0.3 + 0.7 * z,
x * x * 0.5 + z * z * 0.4,
x * z * x + 0.35
]
})),
divisor: 1
},
angle: {
buffer: angleBuffer,
divisor: 1
}
},
elements: bunny.cells,
instances: N * N,
uniforms: {
proj: ({viewportWidth, viewportHeight}) =>
mat4.perspective([],
Math.PI / 2,
viewportWidth / viewportHeight,
0.01,
1000),
model: mat4.identity([]),
view: () => camera.view()
}
})
regl.frame(() => {
regl.clear({
color: [0, 0, 0, 1]
})
// rotate the bunnies every frame.
for (var i = 0; i < N * N; i++) {
angle[i] += 0.01
}
angleBuffer.subdata(angle)
drawBunnies()
camera.tick()
})