Parcourir la source

imrpove LOD and limits

sunag il y a 4 jours
Parent
commit
75669246f9
1 fichiers modifiés avec 37 ajouts et 25 suppressions
  1. 37 25
      examples/webgpu_compute_rasterizer_ibl.html

+ 37 - 25
examples/webgpu_compute_rasterizer_ibl.html

@@ -87,7 +87,7 @@
 			const options = { Output: 'Default', Rasterizer: 'Both', Occlusion: true, Grid: 'XZ' };
 
 			// Buffer visibility packaging configuration — depth occupies the bits above each payload
-			const TRIANGLE_INDEX_BITS = 15; 			// 2^15 = 32768 max triangles in the LOD mega buffer
+			const TRIANGLE_INDEX_BITS = 16; 			// 2^16 = 65536 max triangles in the LOD mega buffer
 			const INSTANCE_INDEX_BITS = 17; 			// 2^17 = 131072 max instances
 			const TRIANGLE_INDEX_MASK = 2 ** TRIANGLE_INDEX_BITS - 1;
 			const INSTANCE_INDEX_MASK = 2 ** INSTANCE_INDEX_BITS - 1;
@@ -190,8 +190,11 @@
 				// Generate LOD geometries and meshlets using Meshopt
 				const lodTargets = [
 					{ ratio: 1.0, error: 0.0, weights: [ 0.25, 0.25, 0.25, 0.5, 0.5 ], flags: [] },
-					{ ratio: 0.12, error: 0.03, weights: [ 0.1, 0.1, 0.1, 0.15, 0.15 ], flags: [ 'RegularizeLight' ] },
-					{ ratio: 0.02, error: 0.15, weights: [ 0.02, 0.02, 0.02, 0.03, 0.03 ], flags: [ 'Regularize' ] }
+					{ ratio: 0.55, error: 0.004, weights: [ 0.2, 0.2, 0.2, 0.35, 0.35 ], flags: [ 'RegularizeLight' ] },
+					{ ratio: 0.25, error: 0.015, weights: [ 0.12, 0.12, 0.12, 0.2, 0.2 ], flags: [ 'RegularizeLight' ] },
+					{ ratio: 0.1, error: 0.05, weights: [ 0.08, 0.08, 0.08, 0.12, 0.12 ], flags: [ 'RegularizeLight' ] },
+					{ ratio: 0.04, error: 0.14, weights: [ 0.04, 0.04, 0.04, 0.06, 0.06 ], flags: [ 'Regularize' ] },
+					{ ratio: 0.015, error: 0.3, weights: [ 0.02, 0.02, 0.02, 0.03, 0.03 ], flags: [ 'Regularize' ] }
 				];
 
 				const geom = sourceMesh.geometry;
@@ -518,11 +521,11 @@
 				// HW Rasterizer Buffers (for large triangles that exceed SW raster budget)
 				const MAX_HW_TRIANGLES = 100000;
 
-				// HW queue: index 0 is atomic counter, indices 1..MAX store payload32
-				const hwQueueData = new Uint32Array( MAX_HW_TRIANGLES + 1 );
+				// HW queue: index 0 is atomic counter, then stride-2 entries [instId, triIdx]
+				const hwQueueData = new Uint32Array( 1 + MAX_HW_TRIANGLES * 2 );
 				const hwQueueAttr = new THREE.StorageBufferAttribute( hwQueueData, 1 );
-				const hwQueueAtomic = storage( hwQueueAttr, 'uint', MAX_HW_TRIANGLES + 1 ).toAtomic();
-				const hwQueueRead = storage( hwQueueAttr, 'uint', MAX_HW_TRIANGLES + 1 ).toReadOnly();
+				const hwQueueAtomic = storage( hwQueueAttr, 'uint', 1 + MAX_HW_TRIANGLES * 2 ).toAtomic();
+				const hwQueueRead = storage( hwQueueAttr, 'uint', 1 + MAX_HW_TRIANGLES * 2 ).toReadOnly();
 
 				// Draw indirect buffer: vertexCount, instanceCount, firstVertex, firstInstance
 				const hwDrawData = new Uint32Array( 4 );
@@ -538,6 +541,7 @@
 				cameraPos = uniform( new THREE.Vector3() );
 				cotHalfFovUniform = uniform( 1.0 );
 				const pixelErrorThresholdUniform = uniform( 1.0 );
+				parameterGroup.add( pixelErrorThresholdUniform, 'value', 0.1, 8.0 ).name( 'LOD Pixel Error' );
 				const maxRasterSizeUniform = uniform( MAX_RASTER_SIZE, 'int' ); // Max bounding box size in pixels for SW rasterizer
 
 				occlusionUniform = uniform( 1, 'uint' );
@@ -811,10 +815,14 @@
 
 								const itemIndex = atomicAdd( workQueueCountAtomic.element( 0 ), 1 );
 
-								// uvec4( instanceIndex, triangleStart, lodNumTriangles, chunkIndex )
-								workQueueBuffer.element( itemIndex ).assign(
-									uvec4( instanceIndex, lodTriStart, lodNumTriangles, uint( chunkIndex ) )
-								);
+								If( itemIndex.lessThan( MAX_WORK_ITEMS ), () => {
+
+									// uvec4( instanceIndex, triangleStart, lodNumTriangles, chunkIndex )
+									workQueueBuffer.element( itemIndex ).assign(
+										uvec4( instanceIndex, lodTriStart, lodNumTriangles, uint( chunkIndex ) )
+									);
+
+								} );
 
 							} );
 
@@ -937,9 +945,8 @@
 										const bbWidth = endX.sub( startX );
 										const bbHeight = endY.sub( startY );
 
-										// Compute payload32 for HW path (full precision)
-										// payload32: instId (17 bits) | megaTriangleIndex (15 bits)
-										const payload32 = instId.shiftLeft( TRIANGLE_INDEX_BITS ).bitOr( megaTriangleIndex.bitAnd( TRIANGLE_INDEX_MASK ) );
+										// HW path payloads — stored as two separate uint entries to
+										// avoid the 32-bit packing limit of instId + triIdx
 
 										// Sub-pixel / Valid bounds rejection + big triangle guard
 										If( startX.lessThanEqual( endX ).and( startY.lessThanEqual( endY ) ).and( bbWidth.lessThanEqual( maxRasterSizeUniform ) ).and( bbHeight.lessThanEqual( maxRasterSizeUniform ) ), () => {
@@ -1041,8 +1048,14 @@
 											If( startX.lessThanEqual( endX ).and( startY.lessThanEqual( endY ) ), () => {
 
 												const hwCount = atomicAdd( hwQueueAtomic.element( 0 ), 1 );
-												const hwSlot = hwCount.add( 1 );
-												atomicStore( hwQueueAtomic.element( hwSlot ), payload32 );
+
+												If( hwCount.lessThan( MAX_HW_TRIANGLES ), () => {
+
+													const hwSlot = hwCount.mul( 2 ).add( 1 );
+													atomicStore( hwQueueAtomic.element( hwSlot ), instId );
+													atomicStore( hwQueueAtomic.element( hwSlot.add( 1 ) ), megaTriangleIndex );
+
+												} );
 
 											} );
 
@@ -1135,7 +1148,8 @@
 					hwGeometry.boundingSphere = new THREE.Sphere().set( new THREE.Vector3(), Infinity );
 
 					// Varyings from the vertex pulling stage
-					const vPayload = varyingProperty( 'uint', 'vPayload' );
+					const vInstId = varyingProperty( 'uint', 'vInstId' );
+					const vMegaTriIdx = varyingProperty( 'uint', 'vMegaTriIdx' );
 					const vUv = varyingProperty( 'vec2', 'vUv' );
 					const vNormal = varyingProperty( 'vec3', 'vNormal' );
 					const vTangent = varyingProperty( 'vec3', 'vTangent' );
@@ -1147,9 +1161,9 @@
 						const triIndex = vertexIndex.div( 3 ); // which triangle in HW queue
 						const localVert = vertexIndex.mod( 3 ); // which vertex (0, 1, 2)
 
-						const payload32 = hwQueueRead.element( triIndex.add( 1 ) );
-						const instId = payload32.shiftRight( TRIANGLE_INDEX_BITS );
-						const megaTriIdx = payload32.bitAnd( TRIANGLE_INDEX_MASK );
+						const hwSlot = triIndex.mul( 2 ).add( 1 );
+						const instId = hwQueueRead.element( hwSlot );
+						const megaTriIdx = hwQueueRead.element( hwSlot.add( 1 ) );
 
 						const matrixWorld = instanceWorldRead.element( instId );
 						const indexOffset = megaTriIdx.mul( 3 );
@@ -1174,7 +1188,8 @@
 						const uv2 = uvBuffer.element( i2 );
 						const uvVal = localVert.equal( 1 ).select( uv1, localVert.equal( 2 ).select( uv2, uv0 ) );
 
-						vPayload.assign( payload32 );
+						vInstId.assign( instId );
+						vMegaTriIdx.assign( megaTriIdx );
 						vUv.assign( uvVal );
 						vNormal.assign( worldNormal );
 						vTangent.assign( computeTangent( w0, w1, w2, uv0, uv1, uv2, worldNormal ) );
@@ -1209,10 +1224,7 @@
 					hwDebugMaterial.positionNode = hwPosition;
 					hwDebugMaterial.fragmentNode = Fn( () => {
 
-						const instId = vPayload.shiftRight( TRIANGLE_INDEX_BITS );
-						const megaTriangleIndex = vPayload.bitAnd( TRIANGLE_INDEX_MASK );
-
-						const meshletId = meshletIdBuffer.element( megaTriangleIndex ).add( instId.mul( 1000 ) );
+						const meshletId = meshletIdBuffer.element( vMegaTriIdx ).add( vInstId.mul( 1000 ) );
 
 						return hashColor( meshletId );
 

粤ICP备19079148号