-
Notifications
You must be signed in to change notification settings - Fork 0
/
3D-cubes-animated.js
190 lines (153 loc) · 5.06 KB
/
3D-cubes-animated.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
const canvasSketch = require("canvas-sketch");
const random = require("canvas-sketch-util/random");
const palettes = require("nice-color-palettes");
global.THREE = require("three");
const settings = {
animate: true,
dimensions: [1024, 1280],
// Get a WebGL canvas rather than 2D
context: "webgl",
// Turn on MSAA
attributes: { antialias: true }
};
const sketch = ({ context, width, height }) => {
// Create a renderer
const renderer = new THREE.WebGLRenderer({
context
});
// WebGL background color
renderer.setClearColor("hsl(0, 0%, 95%)", 1);
// Setup a camera, we will update its settings on resize
const camera = new THREE.OrthographicCamera();
// Setup your scene
const scene = new THREE.Scene();
// Get a palette for our scene
const palette = random.pick(palettes);
// Snap 0..1 point to a -1..1 grid
const grid = (n, gridSize) => {
const max = gridSize - 1;
const snapped = Math.round(n * max) / max;
return snapped * 2 - 1;
};
// Randomize mesh attributes
const randomizeMesh = mesh => {
const gridSize = random.rangeFloor(3, 11);
// Choose a random grid point in a 3D volume between -1..1
const point = new THREE.Vector3(
grid(random.value(), gridSize),
grid(random.value(), gridSize),
grid(random.value(), gridSize)
);
// Stretch it vertically
point.y *= 1.5;
// Scale all the points closer together
point.multiplyScalar(0.5);
point.y -= 0.65;
// Save position
mesh.position.copy(point);
mesh.originalPosition = mesh.position.clone();
// Choose a color for the mesh material
mesh.material.color.set(random.pick(palette));
// Randomly scale each axis
mesh.scale.set(random.gaussian(), random.gaussian(), random.gaussian());
// Do more random scaling on each axis
if (random.chance(0.5)) mesh.scale.x *= random.gaussian();
if (random.chance(0.5)) mesh.scale.y *= random.gaussian();
if (random.chance(0.5)) mesh.scale.z *= random.gaussian();
// Further scale each object
mesh.scale.multiplyScalar(random.gaussian() * 0.25);
// Store the scale
mesh.originalScale = mesh.scale.clone();
// Set some time properties on each mesh
mesh.time = 0;
mesh.duration = random.range(1, 4);
};
// A group that will hold all of our cubes
const container = new THREE.Group();
// Re-use the same Geometry across all our cubes
const geometry = new THREE.BoxGeometry(1, 1, 1);
// The # of cubes to create
const chunks = 50;
// Create each cube and return a THREE.Mesh
const meshes = Array.from(new Array(chunks)).map(() => {
// Basic "unlit" material with no depth
const material = new THREE.MeshStandardMaterial({
metalness: 0,
roughness: 1,
color: random.pick(palette)
});
// Create the mesh
const mesh = new THREE.Mesh(geometry, material);
// Randomize it
randomizeMesh(mesh);
// Set an initially random time
mesh.time = random.range(0, mesh.duration);
return mesh;
});
// Add meshes to the group
meshes.forEach(m => container.add(m));
// Then add the group to the scene
scene.add(container);
// Add a harsh light to the scene
const light = new THREE.DirectionalLight("white", 1);
light.position.set(0, 0, 2);
scene.add(light);
// draw each frame
return {
// Handle resize events here
resize({ pixelRatio, viewportWidth, viewportHeight }) {
renderer.setPixelRatio(pixelRatio);
renderer.setSize(viewportWidth, viewportHeight);
// Setup an isometric perspective
const aspect = viewportWidth / viewportHeight;
const zoom = 1.85;
camera.left = -zoom * aspect;
camera.right = zoom * aspect;
camera.top = zoom;
camera.bottom = -zoom;
camera.near = -100;
camera.far = 100;
camera.position.set(zoom, zoom, zoom);
camera.lookAt(new THREE.Vector3());
// Update camera properties
camera.updateProjectionMatrix();
},
// And render events here
render({ time, deltaTime }) {
// Animate each mesh with noise
meshes.forEach(mesh => {
// Each mesh has its own time that increases each frame
mesh.time += deltaTime;
// If it hits the end of its life, reset it
if (mesh.time > mesh.duration) {
randomizeMesh(mesh);
}
// Scale meshes in and out
mesh.scale.copy(mesh.originalScale);
mesh.scale.multiplyScalar(
Math.sin((mesh.time / mesh.duration) * Math.PI)
);
// Move meshes up
mesh.position.y += deltaTime * 0.5;
// Add slight movement
const f = 0.5;
mesh.scale.y =
mesh.originalScale.y +
0.25 *
random.noise3D(
mesh.originalPosition.x * f,
mesh.originalPosition.y * f,
mesh.originalPosition.z * f,
time * 0.25
);
});
// Draw scene with our camera
renderer.render(scene, camera);
},
// Dispose of WebGL context (optional)
unload() {
renderer.dispose();
}
};
};
canvasSketch(sketch, settings);