浏览代码

ComputeNode: Fix usage (much more particles) (#23944)

* ComputeNode: Fix usage

* cleanup

* cleanup

* fix const to let
sunag 3 年之前
父节点
当前提交
814b0b2891

+ 20 - 4
examples/jsm/nodes/gpgpu/ComputeNode.js

@@ -3,16 +3,32 @@ import { NodeUpdateType } from '../core/constants.js';
 
 
 class ComputeNode extends Node {
 class ComputeNode extends Node {
 
 
-	constructor( dispatchCount, workgroupSize = [ 64 ] ) {
+	constructor( computeNode, count, workgroupSize = [ 64 ] ) {
 
 
 		super( 'void' );
 		super( 'void' );
 
 
-		this.updateType = NodeUpdateType.Object;
+		this.computeNode = computeNode;
 
 
-		this.dispatchCount = dispatchCount;
+		this.count = count;
 		this.workgroupSize = workgroupSize;
 		this.workgroupSize = workgroupSize;
+		this.dispatchCount = 0;
+
+		this.updateType = NodeUpdateType.Object;
+
+		this.updateDispatchCount();
+
+	}
+
+	updateDispatchCount() {
+
+		const { count, workgroupSize } = this;
+
+		let size = workgroupSize[ 0 ];
+
+		for ( let i = 1; i < workgroupSize.length; i ++ )
+			size *= workgroupSize[ i ];
 
 
-		this.computeNode = null;
+		this.dispatchCount = Math.ceil( count / size );
 
 
 	}
 	}
 
 

+ 2 - 2
examples/jsm/nodes/materials/NodeMaterial.js

@@ -41,11 +41,11 @@ class NodeMaterial extends ShaderMaterial {
 
 
 		if ( this.positionNode !== null ) {
 		if ( this.positionNode !== null ) {
 
 
-			vertex = bypass( vertex, assign( vertex, this.positionNode ) );
+			vertex = bypass( vertex, assign( positionLocal, this.positionNode ) );
 
 
 		}
 		}
 
 
-		if ( object.isInstancedMesh === true && builder.isAvailable( 'instance' ) === true ) {
+		if ( object.instanceMatrix?.isInstancedBufferAttribute === true && builder.isAvailable( 'instance' ) === true ) {
 
 
 			vertex = bypass( vertex, instance( object ) );
 			vertex = bypass( vertex, instance( object ) );
 
 

+ 4 - 4
examples/jsm/renderers/webgpu/WebGPUAttributes.js

@@ -73,9 +73,9 @@ class WebGPUAttributes {
 		const size = array.byteLength + ( ( 4 - ( array.byteLength % 4 ) ) % 4 ); // ensure 4 byte alignment, see #20441
 		const size = array.byteLength + ( ( 4 - ( array.byteLength % 4 ) ) % 4 ); // ensure 4 byte alignment, see #20441
 
 
 		const buffer = this.device.createBuffer( {
 		const buffer = this.device.createBuffer( {
-			size: size,
+			size,
 			usage: usage | GPUBufferUsage.COPY_DST,
 			usage: usage | GPUBufferUsage.COPY_DST,
-			mappedAtCreation: true,
+			mappedAtCreation: true
 		} );
 		} );
 
 
 		new array.constructor( buffer.getMappedRange() ).set( array );
 		new array.constructor( buffer.getMappedRange() ).set( array );
@@ -86,8 +86,8 @@ class WebGPUAttributes {
 
 
 		return {
 		return {
 			version: attribute.version,
 			version: attribute.version,
-			buffer: buffer,
-			usage: usage
+			buffer,
+			usage
 		};
 		};
 
 
 	}
 	}

+ 1 - 1
examples/jsm/renderers/webgpu/WebGPUBindings.js

@@ -189,7 +189,7 @@ class WebGPUBindings {
 
 
 					binding.bufferGPU = this.device.createBuffer( {
 					binding.bufferGPU = this.device.createBuffer( {
 						size: byteLength,
 						size: byteLength,
-						usage: binding.usage,
+						usage: binding.usage
 					} );
 					} );
 
 
 				}
 				}

+ 4 - 4
examples/jsm/renderers/webgpu/WebGPUTextureUtils.js

@@ -37,7 +37,7 @@ struct VarysStruct {
 @stage( vertex )
 @stage( vertex )
 fn main( @builtin( vertex_index ) vertexIndex : u32 ) -> VarysStruct {
 fn main( @builtin( vertex_index ) vertexIndex : u32 ) -> VarysStruct {
 
 
-	var Varys: VarysStruct;
+	var Varys : VarysStruct;
 
 
 	var pos = array< vec2<f32>, 4 >(
 	var pos = array< vec2<f32>, 4 >(
 		vec2<f32>( -1.0,  1.0 ),
 		vec2<f32>( -1.0,  1.0 ),
@@ -62,7 +62,7 @@ fn main( @builtin( vertex_index ) vertexIndex : u32 ) -> VarysStruct {
 `;
 `;
 
 
 		const mipmapFragmentSource = `
 		const mipmapFragmentSource = `
-@group( 0 ) @binding( 0 ) 
+@group( 0 ) @binding( 0 )
 var imgSampler : sampler;
 var imgSampler : sampler;
 
 
 @group( 0 ) @binding( 1 )
 @group( 0 ) @binding( 1 )
@@ -100,12 +100,12 @@ fn main( @location( 0 ) vTex : vec2<f32> ) -> @location( 0 ) vec4<f32> {
 			pipeline = this.device.createRenderPipeline( {
 			pipeline = this.device.createRenderPipeline( {
 				vertex: {
 				vertex: {
 					module: this.mipmapVertexShaderModule,
 					module: this.mipmapVertexShaderModule,
-					entryPoint: 'main',
+					entryPoint: 'main'
 				},
 				},
 				fragment: {
 				fragment: {
 					module: this.mipmapFragmentShaderModule,
 					module: this.mipmapFragmentShaderModule,
 					entryPoint: 'main',
 					entryPoint: 'main',
-					targets: [ { format } ],
+					targets: [ { format } ]
 				},
 				},
 				primitive: {
 				primitive: {
 					topology: GPUPrimitiveTopology.TriangleStrip,
 					topology: GPUPrimitiveTopology.TriangleStrip,

+ 1 - 1
examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js

@@ -730,7 +730,7 @@ ${shaderData.codes}
 fn main( ${shaderData.attributes} ) {
 fn main( ${shaderData.attributes} ) {
 
 
 	// system
 	// system
-	instanceIndex = id.x * 3u;
+	instanceIndex = id.x;
 
 
 	// vars
 	// vars
 	${shaderData.vars}
 	${shaderData.vars}

+ 23 - 18
examples/webgpu_compute.html

@@ -30,9 +30,9 @@
 
 
 			import {
 			import {
 				ShaderNode, compute,
 				ShaderNode, compute,
-				uniform, element, storage, temp,
-				assign, add, sub, cond, abs, negate, max, min, length, vec3, color,
-				greaterThanEqual, lessThanEqual, positionLocal, instanceIndex
+				uniform, element, storage, attribute,
+				temp, assign, add, sub, cond, abs, negate, max, min, length, vec3, color,
+				greaterThanEqual, lessThanEqual, instanceIndex
 			} from 'three-nodes/Nodes.js';
 			} from 'three-nodes/Nodes.js';
 
 
 			import { GUI } from './jsm/libs/lil-gui.module.min.js';
 			import { GUI } from './jsm/libs/lil-gui.module.min.js';
@@ -65,29 +65,29 @@
 
 
 				// initialize particles
 				// initialize particles
 
 
-				const particleNum = 65000; // 16-bit limit
-				const particleSize = 3; // vec3
+				const particleNum = 300000;
+				const particleSize = 2; // vec2
 
 
 				const particleArray = new Float32Array( particleNum * particleSize );
 				const particleArray = new Float32Array( particleNum * particleSize );
 				const velocityArray = new Float32Array( particleNum * particleSize );
 				const velocityArray = new Float32Array( particleNum * particleSize );
 
 
-				for ( let i = 0; i < particleArray.length; i += particleSize ) {
+				for ( let i = 0; i < particleNum; i ++ ) {
 
 
-					const r = Math.random() * 0.01 + 0.0005;
+					const r = Math.random() * 0.01 + 0.005;
 					const degree = Math.random() * 360;
 					const degree = Math.random() * 360;
 
 
-					velocityArray[ i + 0 ] = r * Math.sin( degree * Math.PI / 180 );
-					velocityArray[ i + 1 ] = r * Math.cos( degree * Math.PI / 180 );
+					velocityArray[ i * particleSize + 0 ] = r * Math.sin( degree * Math.PI / 180 ); // x
+					velocityArray[ i * particleSize + 1 ] = r * Math.cos( degree * Math.PI / 180 ); // y
 
 
 				}
 				}
 
 
 				// create buffers
 				// create buffers
 
 
-				const particleBuffer = new THREE.BufferAttribute( particleArray, particleSize );
-				const velocityBuffer = new THREE.BufferAttribute( velocityArray, particleSize );
+				const particleBuffer = new THREE.InstancedBufferAttribute( particleArray );
+				const velocityBuffer = new THREE.InstancedBufferAttribute( velocityArray );
 
 
-				const particleBufferNode = storage( particleBuffer, 'vec3' );
-				const velocityBufferNode = storage( velocityBuffer, 'vec3' );
+				const particleBufferNode = storage( particleBuffer, 'vec2', particleNum );
+				const velocityBufferNode = storage( velocityBuffer, 'vec2', particleNum );
 
 
 				// create function
 				// create function
 
 
@@ -116,19 +116,24 @@
 
 
 				// compute
 				// compute
 
 
-				computeNode = compute( particleNum );
-
-				computeNode.computeNode = FnNode;
+				computeNode = compute( FnNode, particleNum );
 
 
 				// use a compute shader to animate the point cloud's vertex data.
 				// use a compute shader to animate the point cloud's vertex data.
 
 
+				const particleNode = attribute( 'particle', 'vec2' );
+
 				const pointsGeometry = new THREE.BufferGeometry();
 				const pointsGeometry = new THREE.BufferGeometry();
-				pointsGeometry.setAttribute( 'position', particleBuffer );
+				pointsGeometry.setAttribute( 'position', new THREE.BufferAttribute( new Float32Array( 3 ) ) ); // single vertex ( not triangle )
+				pointsGeometry.setAttribute( 'particle', particleBuffer ); // dummy the position points as instances
+				pointsGeometry.drawRange.count = 1; // force render points as instances ( not triangle )
 
 
 				const pointsMaterial = new Nodes.PointsNodeMaterial();
 				const pointsMaterial = new Nodes.PointsNodeMaterial();
-				pointsMaterial.colorNode = add( positionLocal, color( 0xFFFFFF ) );
+				pointsMaterial.colorNode = add( particleNode, color( 0xFFFFFF ) );
+				pointsMaterial.positionNode = particleNode;
 
 
 				const mesh = new THREE.Points( pointsGeometry, pointsMaterial );
 				const mesh = new THREE.Points( pointsGeometry, pointsMaterial );
+				mesh.isInstancedMesh = true;
+				mesh.count = particleNum;
 				scene.add( mesh );
 				scene.add( mesh );
 
 
 				renderer = new WebGPURenderer();
 				renderer = new WebGPURenderer();