|
1 | 1 | <html lang="en"> |
2 | 2 | <head> |
3 | | - <title>three.js - WebGPU - Compute Particles</title> |
| 3 | + <title>three.js webgpu - compute particles</title> |
4 | 4 | <meta charset="utf-8"> |
5 | 5 | <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> |
6 | | - <link type="text/css" rel="stylesheet" href="main.css"> |
| 6 | + <link type="text/css" rel="stylesheet" href="example.css"> |
7 | 7 | </head> |
8 | 8 | <body> |
9 | 9 |
|
10 | 10 | <div id="info"> |
11 | | - <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> WebGPU - Compute - 500k Particles |
12 | | - <div id="timestamps" style=" |
13 | | - position: absolute; |
14 | | - top: 60px; |
15 | | - left: 0; |
16 | | - padding: 10px; |
17 | | - background: rgba( 0, 0, 0, 0.5 ); |
18 | | - color: #fff; |
19 | | - font-family: monospace; |
20 | | - font-size: 12px; |
21 | | - line-height: 1.5; |
22 | | - pointer-events: none; |
23 | | - text-align: left; |
24 | | - "></div> |
| 11 | + <a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a> |
| 12 | + |
| 13 | + <div class="title-wrapper"> |
| 14 | + <a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Compute Particles</span> |
| 15 | + </div> |
| 16 | + |
| 17 | + <small>500k Particles.</small> |
25 | 18 | </div> |
26 | 19 |
|
27 | 20 | <script type="importmap"> |
|
41 | 34 | import { Fn, If, uniform, float, uv, vec3, hash, shapeCircle, |
42 | 35 | instancedArray, instanceIndex } from 'three/tsl'; |
43 | 36 |
|
44 | | - import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; |
45 | | - import Stats from 'three/addons/libs/stats.module.js'; |
| 37 | + import { Inspector } from 'three/addons/inspector/Inspector.js'; |
46 | 38 |
|
47 | | - import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; |
| 39 | + import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; |
48 | 40 |
|
49 | 41 | const particleCount = 200000; |
50 | 42 |
|
|
56 | 48 | const clickPosition = uniform( new THREE.Vector3() ); |
57 | 49 |
|
58 | 50 | let camera, scene, renderer; |
59 | | - let controls, stats; |
| 51 | + let controls; |
60 | 52 | let computeParticles; |
61 | 53 |
|
62 | 54 | let isOrbitControlsActive; |
63 | 55 |
|
64 | | - const timestamps = document.getElementById( 'timestamps' ); |
65 | | - |
66 | 56 | init(); |
67 | 57 |
|
68 | 58 | function init() { |
|
100 | 90 | color.x = hash( instanceIndex ); |
101 | 91 | color.y = hash( instanceIndex.add( 2 ) ); |
102 | 92 |
|
103 | | - } )().compute( particleCount ); |
| 93 | + } )().compute( particleCount ).setName( 'Init Particles' ); |
104 | 94 |
|
105 | 95 | // |
106 | 96 |
|
|
130 | 120 |
|
131 | 121 | } ); |
132 | 122 |
|
133 | | - computeParticles = computeUpdate().compute( particleCount ); |
| 123 | + computeParticles = computeUpdate().compute( particleCount ).setName( 'Update Particles' ); |
134 | 124 |
|
135 | 125 | // create particles |
136 | 126 |
|
|
163 | 153 |
|
164 | 154 | // |
165 | 155 |
|
166 | | - renderer = new THREE.WebGPURenderer( { antialias: true, trackTimestamp: true } ); |
| 156 | + renderer = new THREE.WebGPURenderer( { antialias: true } ); |
167 | 157 | renderer.setPixelRatio( window.devicePixelRatio ); |
168 | 158 | renderer.setSize( window.innerWidth, window.innerHeight ); |
169 | 159 | renderer.setAnimationLoop( animate ); |
| 160 | + renderer.inspector = new Inspector(); |
170 | 161 | document.body.appendChild( renderer.domElement ); |
171 | 162 |
|
172 | | - stats = new Stats(); |
173 | | - document.body.appendChild( stats.dom ); |
174 | | - |
175 | 163 | // |
176 | 164 |
|
177 | 165 | renderer.computeAsync( computeInit ); |
|
192 | 180 |
|
193 | 181 | velocity.assign( velocity.add( direction.mul( relativePower ) ) ); |
194 | 182 |
|
195 | | - } )().compute( particleCount ); |
| 183 | + } )().compute( particleCount ).setName( 'Hit Particles' ); |
196 | 184 |
|
197 | 185 | // |
198 | 186 |
|
|
256 | 244 |
|
257 | 245 | // gui |
258 | 246 |
|
259 | | - const gui = new GUI(); |
| 247 | + const gui = renderer.inspector.createParameters( 'Settings' ); |
260 | 248 |
|
261 | 249 | gui.add( gravity, 'value', - .0098, 0, 0.0001 ).name( 'gravity' ); |
262 | 250 | gui.add( bounce, 'value', .1, 1, 0.01 ).name( 'bounce' ); |
|
276 | 264 |
|
277 | 265 | } |
278 | 266 |
|
279 | | - async function animate() { |
280 | | - |
281 | | - stats.update(); |
| 267 | + function animate() { |
282 | 268 |
|
283 | 269 | controls.update(); |
284 | 270 |
|
285 | | - await renderer.computeAsync( computeParticles ); |
286 | | - renderer.resolveTimestampsAsync( THREE.TimestampQuery.COMPUTE ); |
287 | | - |
288 | | - await renderer.renderAsync( scene, camera ); |
289 | | - renderer.resolveTimestampsAsync( THREE.TimestampQuery.RENDER ); |
290 | | - |
291 | | - // throttle the logging |
292 | | - |
293 | | - if ( renderer.hasFeature( 'timestamp-query' ) ) { |
294 | | - |
295 | | - if ( renderer.info.render.calls % 5 === 0 ) { |
296 | | - |
297 | | - timestamps.innerHTML = ` |
298 | | -
|
299 | | - Compute ${renderer.info.compute.frameCalls} pass in ${renderer.info.compute.timestamp.toFixed( 6 )}ms<br> |
300 | | - Draw ${renderer.info.render.drawCalls} pass in ${renderer.info.render.timestamp.toFixed( 6 )}ms`; |
301 | | - |
302 | | - } |
303 | | - |
304 | | - } else { |
305 | | - |
306 | | - timestamps.innerHTML = 'Timestamp queries not supported'; |
307 | | - |
308 | | - } |
309 | | - |
| 271 | + renderer.compute( computeParticles ); |
| 272 | + renderer.render( scene, camera ); |
310 | 273 |
|
311 | 274 | } |
312 | 275 |
|
|
0 commit comments