Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified examples/screenshots/webgpu_compute_particles_rain.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 38 additions & 7 deletions examples/webgpu_compute_particles_rain.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<script type="module">

import * as THREE from 'three/webgpu';
import { Fn, texture, uv, uint, instancedArray, positionWorld, billboarding, time, hash, deltaTime, vec2, instanceIndex, positionGeometry, If } from 'three/tsl';
import { Fn, texture, uv, uint, instancedArray, positionWorld, billboarding, time, hash, deltaTime, vec2, instanceIndex, positionGeometry, If, storage, uniform } from 'three/tsl';

import { Inspector } from 'three/addons/inspector/Inspector.js';

Expand All @@ -40,17 +40,26 @@
import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';

const maxParticleCount = 50000;
const workgroupSize = 64;
const instanceCount = maxParticleCount / 2;
const startNumWorkgroups = Math.ceil( instanceCount / workgroupSize );

const workgroupGridIndirectBuffer = new THREE.IndirectStorageBufferAttribute( new Uint32Array( [ startNumWorkgroups, 1, 1 ] ), 1 );
const workgroupGridStorage = storage( workgroupGridIndirectBuffer, 'uint', 3 );

let camera, scene, renderer;
let controls;
let computeParticles;
let computeParticles, computeWorkgroupsDispatched;
let monkey;
let clock;

let collisionBox, collisionCamera, collisionPosRT, collisionPosMaterial;
let collisionBoxPos, collisionBoxPosUI;

const effectController = {
particlesCount: uniform( uint( instanceCount ) )
};

init();

async function init() {
Expand Down Expand Up @@ -108,6 +117,16 @@

const randUint = () => uint( Math.random() * 0xFFFFFF );

computeWorkgroupsDispatched = Fn( () => {

const { particlesCount } = effectController;

const numWorkgroupsToDispatch = ( particlesCount.sub( 1 ) ).div( workgroupSize ).add( 1 );

workgroupGridStorage.element( 0 ).assign( numWorkgroupsToDispatch );

} )().compute( 1 );

const computeInit = Fn( () => {

const position = positionBuffer.element( instanceIndex );
Expand Down Expand Up @@ -185,7 +204,12 @@

} );

computeParticles = computeUpdate().compute( maxParticleCount ).setName( 'Particles' );
// When computing indirectly on the Renderer's WebGPUBackend, the count is ignored and only the dispatch size
// is equal to the product of the workgroup size by the dispatch grid. However, the WebGLBackend does not
// have any conception of indirect compute, workgroup sizes, or dispatch grids. Accordingly, in order for the example
// to function on both the WebGPUBackend and the WebGLBackend, the total number of computed particles still needs to be provided
// as the ComputeNode's count argument.
computeParticles = computeUpdate().compute( maxParticleCount, [ 64, 1, 1 ] ).setName( 'Particles' );

// rain

Expand Down Expand Up @@ -316,9 +340,14 @@
collisionBoxPosUI = new THREE.Vector3().copy( collisionBox.position );
collisionBoxPos = new THREE.Vector3();

gui.add( collisionBoxPosUI, 'z', - 50, 50, .001 ).name( 'position' );
gui.add( collisionBox.scale, 'x', .1, 3.5, 0.01 ).name( 'scale' );
gui.add( rainParticles, 'count', 200, maxParticleCount, 1 ).name( 'drop count' ).onChange( ( v ) => rippleParticles.count = v );
gui.add( collisionBoxPosUI, 'z', - 50, 50, .001 ).name( 'awning position' );
gui.add( collisionBox.scale, 'x', .1, 3.5, 0.01 ).name( 'awning size' );
gui.add( effectController.particlesCount, 'value', 200, maxParticleCount, 1 ).name( 'drop count' ).onChange( ( v ) => {

rainParticles.count = v;
rippleParticles.count = v;

} );

}

Expand Down Expand Up @@ -356,7 +385,9 @@

// compute

renderer.compute( computeParticles );

renderer.compute( computeWorkgroupsDispatched );
renderer.compute( computeParticles, workgroupGridIndirectBuffer );

// result

Expand Down
2 changes: 1 addition & 1 deletion src/renderers/common/Renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2424,7 +2424,7 @@ class Renderer {
* @param {number|Array<number>|IndirectStorageBufferAttribute} [dispatchSize=null]
* - A single number representing count, or
* - An array [x, y, z] representing dispatch size, or
* - A IndirectStorageBufferAttribute for indirect dispatch size.
* - A IndirectStorageBufferAttribute for indirect dispatch containing the X, Y, and Z dimensions of the grid of workgroups.
* @return {Promise|undefined} A Promise that resolve when the compute has finished. Only returned when the renderer has not been initialized.
*/
compute( computeNodes, dispatchSize = null ) {
Expand Down