Browse Source

WebGPURenderer: instance mesh use binding group instead of attribute (#28726)

* feat: make instanceMatrixNode a binding group

* feat: make instance color binding group

* fix: fix deepscan check

* fix: fix exmaple error

* chore: revert instance color
ypy 1 year ago
parent
commit
d8621e868e
1 changed files with 34 additions and 15 deletions
  1. 34 15
      src/nodes/accessors/InstanceNode.js

+ 34 - 15
src/nodes/accessors/InstanceNode.js

@@ -5,6 +5,8 @@ import { normalLocal } from './NormalNode.js';
 import { positionLocal } from './PositionNode.js';
 import { positionLocal } from './PositionNode.js';
 import { nodeProxy, vec3, mat3, mat4 } from '../shadernode/ShaderNode.js';
 import { nodeProxy, vec3, mat3, mat4 } from '../shadernode/ShaderNode.js';
 import { NodeUpdateType } from '../core/constants.js';
 import { NodeUpdateType } from '../core/constants.js';
+import { buffer } from '../accessors/BufferNode.js';
+import { instanceIndex } from '../core/IndexNode.js';
 
 
 import { InstancedInterleavedBuffer } from '../../core/InstancedInterleavedBuffer.js';
 import { InstancedInterleavedBuffer } from '../../core/InstancedInterleavedBuffer.js';
 import { InstancedBufferAttribute } from '../../core/InstancedBufferAttribute.js';
 import { InstancedBufferAttribute } from '../../core/InstancedBufferAttribute.js';
@@ -32,26 +34,39 @@ class InstanceNode extends Node {
 	setup( /*builder*/ ) {
 	setup( /*builder*/ ) {
 
 
 		let instanceMatrixNode = this.instanceMatrixNode;
 		let instanceMatrixNode = this.instanceMatrixNode;
+		let instanceColorNode = this.instanceColorNode;
 
 
 		const instanceMesh = this.instanceMesh;
 		const instanceMesh = this.instanceMesh;
 
 
 		if ( instanceMatrixNode === null ) {
 		if ( instanceMatrixNode === null ) {
 
 
 			const instanceAttribute = instanceMesh.instanceMatrix;
 			const instanceAttribute = instanceMesh.instanceMatrix;
-			const buffer = new InstancedInterleavedBuffer( instanceAttribute.array, 16, 1 );
 
 
-			this.buffer = buffer;
-			const bufferFn = instanceAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
+			// Both WebGPU and WebGL backends have UBO max limited to 64kb. Matrix count number bigger than 1000 ( 16 * 4 * 1000 = 64kb ) will fallback to attribute.
 
 
-			const instanceBuffers = [
-				// F.Signature -> bufferAttribute( array, type, stride, offset )
-				bufferFn( buffer, 'vec4', 16, 0 ),
-				bufferFn( buffer, 'vec4', 16, 4 ),
-				bufferFn( buffer, 'vec4', 16, 8 ),
-				bufferFn( buffer, 'vec4', 16, 12 )
-			];
+			if ( instanceMesh.count <= 1000 ) {
 
 
-			instanceMatrixNode = mat4( ...instanceBuffers );
+				instanceMatrixNode = buffer( instanceAttribute.array, 'mat4', instanceMesh.count ).element( instanceIndex );
+
+			} else {
+
+				const buffer = new InstancedInterleavedBuffer( instanceAttribute.array, 16, 1 );
+
+				this.buffer = buffer;
+
+				const bufferFn = instanceAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
+
+				const instanceBuffers = [
+					// F.Signature -> bufferAttribute( array, type, stride, offset )
+					bufferFn( buffer, 'vec4', 16, 0 ),
+					bufferFn( buffer, 'vec4', 16, 4 ),
+					bufferFn( buffer, 'vec4', 16, 8 ),
+					bufferFn( buffer, 'vec4', 16, 12 )
+				];
+
+				instanceMatrixNode = mat4( ...instanceBuffers );
+
+			}
 
 
 			this.instanceMatrixNode = instanceMatrixNode;
 			this.instanceMatrixNode = instanceMatrixNode;
 
 
@@ -59,13 +74,17 @@ class InstanceNode extends Node {
 
 
 		const instanceColorAttribute = instanceMesh.instanceColor;
 		const instanceColorAttribute = instanceMesh.instanceColor;
 
 
-		if ( instanceColorAttribute && this.instanceColorNode === null ) {
+		if ( instanceColorAttribute && instanceColorNode === null ) {
 
 
 			const buffer = new InstancedBufferAttribute( instanceColorAttribute.array, 3 );
 			const buffer = new InstancedBufferAttribute( instanceColorAttribute.array, 3 );
+
 			const bufferFn = instanceColorAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
 			const bufferFn = instanceColorAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
 
 
 			this.bufferColor = buffer;
 			this.bufferColor = buffer;
-			this.instanceColorNode = vec3( bufferFn( buffer, 'vec3', 3, 0 ) );
+
+			instanceColorNode = vec3( bufferFn( buffer, 'vec3', 3, 0 ) );
+
+			this.instanceColorNode = instanceColorNode;
 
 
 		}
 		}
 
 
@@ -98,13 +117,13 @@ class InstanceNode extends Node {
 
 
 	update( /*frame*/ ) {
 	update( /*frame*/ ) {
 
 
-		if ( this.instanceMesh.instanceMatrix.usage !== DynamicDrawUsage && this.instanceMesh.instanceMatrix.version !== this.buffer.version ) {
+		if ( this.instanceMesh.instanceMatrix.usage !== DynamicDrawUsage && this.buffer != null && this.instanceMesh.instanceMatrix.version !== this.buffer.version ) {
 
 
 			this.buffer.version = this.instanceMesh.instanceMatrix.version;
 			this.buffer.version = this.instanceMesh.instanceMatrix.version;
 
 
 		}
 		}
 
 
-		if ( this.instanceMesh.instanceColor && this.instanceMesh.instanceColor.usage !== DynamicDrawUsage && this.instanceMesh.instanceColor.version !== this.bufferColor.version ) {
+		if ( this.instanceMesh.instanceColor && this.instanceMesh.instanceColor.usage !== DynamicDrawUsage && this.bufferColor != null && this.instanceMesh.instanceColor.version !== this.bufferColor.version ) {
 
 
 			this.bufferColor.version = this.instanceMesh.instanceColor.version;
 			this.bufferColor.version = this.instanceMesh.instanceColor.version;