Skip to content

Commit 37e3bb7

Browse files
Mugen87RuthySheffi
authored andcommitted
Examples: Make dynamic instancing demo more interesting. (mrdoob#31058)
1 parent 43a214a commit 37e3bb7

File tree

3 files changed

+132
-52
lines changed

3 files changed

+132
-52
lines changed
93.9 KB
Loading

examples/textures/edge3.jpg

2.48 KB
Loading

examples/webgl_instancing_dynamic.html

Lines changed: 132 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
<link type="text/css" rel="stylesheet" href="main.css">
88
</head>
99
<body>
10+
<div id="info">
11+
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - instancing - dynamic<br/>
12+
Based on <a href="https://web.archive.org/web/20210101053442/http://oos.moxiecode.com/js_webgl/cubescape/" target="_blank" rel="noopener">Cubescape</a>
13+
by <a href="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/oosmoxiecode" target="_blank" rel="noopener">oosmoxiecode</a>
14+
</div>
15+
1016
<script type="importmap">
1117
{
1218
"imports": {
@@ -20,64 +26,119 @@
2026

2127
import * as THREE from 'three';
2228

23-
import Stats from 'three/addons/libs/stats.module.js';
24-
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
29+
import { Timer } from 'three/addons/misc/Timer.js';
30+
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
31+
import TWEEN from 'three/addons/libs/tween.module.js';
32+
33+
let camera, scene, renderer, timer, mesh;
2534

26-
let camera, scene, renderer, stats;
35+
const amount = 100;
2736

28-
let mesh;
29-
const amount = parseInt( window.location.search.slice( 1 ) ) || 10;
30-
const count = Math.pow( amount, 3 );
37+
const count = Math.pow( amount, 2 );
3138
const dummy = new THREE.Object3D();
3239

40+
const seeds = [];
41+
const baseColors = [];
42+
43+
const color = new THREE.Color();
44+
const colors = [ new THREE.Color( 0x00ffff ), new THREE.Color( 0xffff00 ), new THREE.Color( 0xff00ff ) ];
45+
const animation = { t: 0 };
46+
let currentColorIndex = 0;
47+
let nextColorIndex = 1;
48+
49+
const maxDistance = 75;
50+
const cameraTarget = new THREE.Vector3();
51+
3352
init();
3453

3554
function init() {
3655

56+
renderer = new THREE.WebGLRenderer( { antialias: true } );
57+
renderer.setPixelRatio( window.devicePixelRatio );
58+
renderer.setSize( window.innerWidth, window.innerHeight );
59+
renderer.toneMapping = THREE.NeutralToneMapping;
60+
renderer.setAnimationLoop( animate );
61+
document.body.appendChild( renderer.domElement );
62+
3763
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1, 100 );
38-
camera.position.set( amount * 0.9, amount * 0.9, amount * 0.9 );
64+
camera.position.set( 10, 10, 10 );
3965
camera.lookAt( 0, 0, 0 );
4066

67+
const pmremGenerator = new THREE.PMREMGenerator( renderer );
68+
4169
scene = new THREE.Scene();
70+
scene.background = new THREE.Color( 0xadd8e6 );
71+
scene.environment = pmremGenerator.fromScene( new RoomEnvironment(), 0.04 ).texture;
4272

43-
const loader = new THREE.BufferGeometryLoader();
44-
loader.load( 'models/json/suzanne_buffergeometry.json', function ( geometry ) {
73+
timer = new Timer();
74+
timer.connect( document );
4575

46-
geometry.computeVertexNormals();
47-
geometry.scale( 0.5, 0.5, 0.5 );
76+
const loader = new THREE.TextureLoader();
77+
const texture = loader.load( 'textures/edge3.jpg' );
78+
texture.colorSpace = THREE.SRGBColorSpace;
4879

49-
const material = new THREE.MeshNormalMaterial();
50-
// check overdraw
51-
// let material = new THREE.MeshBasicMaterial( { color: 0xff0000, opacity: 0.1, transparent: true } );
80+
const geometry = new THREE.BoxGeometry();
81+
const material = new THREE.MeshStandardMaterial( { map: texture } );
5282

53-
mesh = new THREE.InstancedMesh( geometry, material, count );
54-
mesh.instanceMatrix.setUsage( THREE.DynamicDrawUsage ); // will be updated every frame
55-
scene.add( mesh );
83+
mesh = new THREE.InstancedMesh( geometry, material, count );
84+
mesh.instanceMatrix.setUsage( THREE.DynamicDrawUsage ); // will be updated every frame
85+
scene.add( mesh );
5686

57-
//
87+
let i = 0;
88+
const offset = ( amount - 1 ) / 2;
5889

59-
const gui = new GUI();
60-
gui.add( mesh, 'count', 0, count );
90+
for ( let x = 0; x < amount; x ++ ) {
6191

62-
} );
92+
for ( let z = 0; z < amount; z ++ ) {
6393

64-
//
94+
dummy.position.set( offset - x, 0, offset - z );
95+
dummy.scale.set( 1, 2, 1 );
6596

66-
renderer = new THREE.WebGLRenderer( { antialias: true } );
67-
renderer.setPixelRatio( window.devicePixelRatio );
68-
renderer.setSize( window.innerWidth, window.innerHeight );
69-
renderer.setAnimationLoop( animate );
70-
document.body.appendChild( renderer.domElement );
97+
dummy.updateMatrix();
7198

72-
//
99+
color.setHSL( 1, 0.5 + ( Math.random() * 0.5 ), 0.5 + ( Math.random() * 0.5 ) );
100+
baseColors.push( color.getHex() );
101+
102+
mesh.setMatrixAt( i, dummy.matrix );
103+
mesh.setColorAt( i, color.multiply( colors[ 0 ] ) );
104+
105+
i ++;
106+
107+
seeds.push( Math.random() );
73108

74-
stats = new Stats();
75-
document.body.appendChild( stats.dom );
109+
}
110+
111+
}
76112

77113
//
78114

79115
window.addEventListener( 'resize', onWindowResize );
80116

117+
setInterval( startTween, 3000 );
118+
119+
}
120+
121+
function startTween() {
122+
123+
// tween for animating color transition
124+
125+
new TWEEN.Tween( animation )
126+
.to( {
127+
t: 1
128+
}, 2000 )
129+
.easing( TWEEN.Easing.Sinusoidal.In )
130+
.onComplete( () => {
131+
132+
animation.t = 0;
133+
134+
currentColorIndex = nextColorIndex;
135+
nextColorIndex ++;
136+
137+
if ( nextColorIndex >= colors.length ) nextColorIndex = 0;
138+
139+
} )
140+
.start();
141+
81142
}
82143

83144
function onWindowResize() {
@@ -93,49 +154,68 @@
93154

94155
function animate() {
95156

96-
render();
157+
timer.update();
97158

98-
stats.update();
159+
const time = timer.getElapsed();
99160

100-
}
161+
TWEEN.update();
162+
163+
// animate camera
164+
165+
camera.position.x = Math.sin( time / 4 ) * 10;
166+
camera.position.z = Math.cos( time / 4 ) * 10;
167+
camera.position.y = 8 + Math.cos( time / 2 ) * 2;
168+
169+
cameraTarget.x = Math.sin( time / 4 ) * - 8;
170+
cameraTarget.z = Math.cos( time / 2 ) * - 8;
171+
172+
camera.lookAt( cameraTarget );
101173

102-
function render() {
174+
camera.up.x = Math.sin( time / 400 );
103175

104-
if ( mesh ) {
176+
// animate instance positions and colors
105177

106-
const time = Date.now() * 0.001;
178+
for ( let i = 0; i < mesh.count; i ++ ) {
107179

108-
mesh.rotation.x = Math.sin( time / 4 );
109-
mesh.rotation.y = Math.sin( time / 2 );
180+
mesh.getMatrixAt( i, dummy.matrix );
181+
dummy.matrix.decompose( dummy.position, dummy.quaternion, dummy.scale );
110182

111-
let i = 0;
112-
const offset = ( amount - 1 ) / 2;
183+
dummy.position.y = Math.abs( Math.sin( ( time + seeds[ i ] ) * 2 + seeds[ i ] ) );
113184

114-
for ( let x = 0; x < amount; x ++ ) {
185+
dummy.updateMatrix();
115186

116-
for ( let y = 0; y < amount; y ++ ) {
187+
mesh.setMatrixAt( i, dummy.matrix );
117188

118-
for ( let z = 0; z < amount; z ++ ) {
189+
// colors
119190

120-
dummy.position.set( offset - x, offset - y, offset - z );
121-
dummy.rotation.y = ( Math.sin( x / 4 + time ) + Math.sin( y / 4 + time ) + Math.sin( z / 4 + time ) );
122-
dummy.rotation.z = dummy.rotation.y * 2;
191+
if ( animation.t > 0 ) {
123192

124-
dummy.updateMatrix();
193+
const currentColor = colors[ currentColorIndex ];
194+
const nextColor = colors[ nextColorIndex ];
195+
196+
const f = dummy.position.length() / maxDistance;
125197

126-
mesh.setMatrixAt( i ++, dummy.matrix );
198+
if ( f <= animation.t ) {
127199

128-
}
200+
color.set( baseColors[ i ] ).multiply( nextColor );
201+
202+
} else {
203+
204+
color.set( baseColors[ i ] ).multiply( currentColor );
129205

130206
}
131207

132-
}
208+
mesh.setColorAt( i, color );
133209

134-
mesh.instanceMatrix.needsUpdate = true;
135-
mesh.computeBoundingSphere();
210+
}
136211

137212
}
138213

214+
mesh.instanceMatrix.needsUpdate = true;
215+
if ( animation.t > 0 ) mesh.instanceColor.needsUpdate = true;
216+
217+
mesh.computeBoundingSphere();
218+
139219
renderer.render( scene, camera );
140220

141221
}

0 commit comments

Comments
 (0)