@@ -425,12 +425,26 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
425425 }
426426 } ;
427427
428+ publicAPI . isEdgePrimitive = ( ) =>
429+ model . primitiveType === PrimitiveTypes . TriangleEdges ||
430+ model . primitiveType === PrimitiveTypes . TriangleStripEdges ;
431+
432+ publicAPI . shouldSkipPass = ( ) =>
433+ publicAPI . isEdgePrimitive ( ) && ( model . depthOnlyPass || model . selectionPass ) ;
434+
428435 // Renders myself
429436 publicAPI . renderForPass = ( renderEncoder , depthOnly = false ) => {
430437 model . depthOnlyPass = depthOnly ;
438+ model . selectionPass = renderEncoder ?. getPipelineHash ?. ( ) === 'sel' ;
439+ if ( publicAPI . shouldSkipPass ( ) ) {
440+ model . depthOnlyPass = false ;
441+ model . selectionPass = false ;
442+ return ;
443+ }
431444 publicAPI . prepareToDraw ( renderEncoder ) ;
432445 model . renderEncoder . registerDrawCallback ( model . pipeline , publicAPI . draw ) ;
433446 model . depthOnlyPass = false ;
447+ model . selectionPass = false ;
434448 } ;
435449
436450 publicAPI . translucentPass = ( prepass ) => {
@@ -458,8 +472,10 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
458472 const ppty = actor . getProperty ( ) ;
459473 const clippingPlanesMTime = model . renderable . getClippingPlanesMTime ( ) ;
460474 const backfaceProperty = actor . getBackfaceProperty ?. ( ) ?? ppty ;
475+ const selector = model . WebGPURenderer ?. getSelector ?. ( ) ;
461476 const utime = model . UBO . getSendTime ( ) ;
462477 if (
478+ ! selector &&
463479 publicAPI . getMTime ( ) <= utime &&
464480 ppty . getMTime ( ) <= utime &&
465481 backfaceProperty . getMTime ( ) <= utime &&
@@ -573,7 +589,13 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
573589 'Opacity' ,
574590 edgeLikeRepresentation ? ppty . getEdgeOpacity ( ) : ppty . getOpacity ( )
575591 ) ;
576- model . UBO . setValue ( 'PropID' , model . WebGPUActor . getPropID ( ) ) ;
592+ const runtimePropID = model . WebGPUActor . getPropID ( ) ;
593+ model . UBO . setValue (
594+ 'PropID' ,
595+ selector ?. getPropIDForSelection
596+ ? selector . getPropIDForSelection ( runtimePropID , actor ) + 1
597+ : runtimePropID
598+ ) ;
577599 const cp = publicAPI . getCoincidentParameters ( ) ;
578600 model . UBO . setValue ( 'CoincidentFactor' , cp . factor ) ;
579601 model . UBO . setValue ( 'CoincidentOffset' , cp . offset ) ;
@@ -1210,12 +1232,40 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
12101232
12111233 publicAPI . replaceShaderSelect = ( hash , pipeline , vertexInput ) => {
12121234 if ( hash . includes ( 'sel' ) ) {
1235+ const selectBuffer = vertexInput . getBuffer ( 'selectId' ) ;
1236+ if ( selectBuffer ) {
1237+ const vDesc = pipeline . getShaderDescription ( 'vertex' ) ;
1238+ vDesc . addOutput (
1239+ 'u32' ,
1240+ 'attributeID' ,
1241+ selectBuffer . getArrayInformation ( ) [ 0 ] . interpolation
1242+ ) ;
1243+ vDesc . addOutput (
1244+ 'u32' ,
1245+ 'compositeID' ,
1246+ selectBuffer . getArrayInformation ( ) [ 0 ] . interpolation
1247+ ) ;
1248+ let code = vDesc . getCode ( ) ;
1249+ code = vtkWebGPUShaderCache . substitute ( code , '//VTK::Select::Impl' , [
1250+ ' output.compositeID = mapperUBO.PropID;' ,
1251+ ' output.attributeID = selectId;' ,
1252+ ] ) . result ;
1253+ vDesc . setCode ( code ) ;
1254+ }
1255+
12131256 const fDesc = pipeline . getShaderDescription ( 'fragment' ) ;
12141257 let code = fDesc . getCode ( ) ;
1215- // by default there are no composites, so just 0
1216- code = vtkWebGPUShaderCache . substitute ( code , '//VTK::Select::Impl' , [
1217- ' var compositeID: u32 = 0u;' ,
1218- ] ) . result ;
1258+ const selectImpl = selectBuffer
1259+ ? [
1260+ ' var compositeID: u32 = input.compositeID;' ,
1261+ ' var attributeID: u32 = input.attributeID;' ,
1262+ ]
1263+ : [ ' var compositeID: u32 = 0u;' , ' var attributeID: u32 = 0u;' ] ;
1264+ code = vtkWebGPUShaderCache . substitute (
1265+ code ,
1266+ '//VTK::Select::Impl' ,
1267+ selectImpl
1268+ ) . result ;
12191269 fDesc . setCode ( code ) ;
12201270 }
12211271 } ;
@@ -1451,6 +1501,43 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
14511501 } else {
14521502 vertexInput . removeBufferIfPresent ( 'tcoord' ) ;
14531503 }
1504+
1505+ // --- Selection IDs ---
1506+ const selector = model . WebGPURenderer ?. getSelector ?. ( ) ;
1507+ if ( selector && ! edges && indexBuffer ) {
1508+ let selectIds = null ;
1509+ if (
1510+ selector . getFieldAssociation ( ) ===
1511+ FieldAssociations . FIELD_ASSOCIATION_POINTS
1512+ ) {
1513+ selectIds = indexBuffer . getFlatIdToPointId ( ) ;
1514+ } else if (
1515+ selector . getFieldAssociation ( ) ===
1516+ FieldAssociations . FIELD_ASSOCIATION_CELLS
1517+ ) {
1518+ selectIds = indexBuffer . getFlatIdToCellId ( ) ;
1519+ }
1520+
1521+ if ( selectIds ) {
1522+ vertexInput . addBuffer (
1523+ device . getBufferManager ( ) . getBuffer ( {
1524+ hash : `sel${ selector . getFieldAssociation ( ) } I${ indexBuffer . getMTime ( ) } ` ,
1525+ usage : BufferUsage . RawVertex ,
1526+ format : 'uint32' ,
1527+ interpolation : 'flat' ,
1528+ nativeArray :
1529+ selectIds instanceof Uint32Array
1530+ ? selectIds
1531+ : Uint32Array . from ( selectIds ) ,
1532+ } ) ,
1533+ [ 'selectId' ]
1534+ ) ;
1535+ } else {
1536+ vertexInput . removeBufferIfPresent ( 'selectId' ) ;
1537+ }
1538+ } else {
1539+ vertexInput . removeBufferIfPresent ( 'selectId' ) ;
1540+ }
14541541 } ;
14551542
14561543 publicAPI . updateTextures = ( ) => {
@@ -1573,6 +1660,9 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
15731660 if ( model . depthOnlyPass ) {
15741661 pipelineHash += 'd' ;
15751662 }
1663+ if ( model . selectionPass ) {
1664+ pipelineHash += 's' ;
1665+ }
15761666
15771667 if (
15781668 model . primitiveType === PrimitiveTypes . TriangleEdges ||
@@ -1651,6 +1741,7 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
16511741
16521742const DEFAULT_VALUES = {
16531743 depthOnlyPass : false ,
1744+ selectionPass : false ,
16541745 is2D : false ,
16551746 cellArray : null ,
16561747 currentInput : null ,
0 commit comments