@@ -7,6 +7,7 @@ import vtkWebGPUUniformBuffer from 'vtk.js/Sources/Rendering/WebGPU/UniformBuffe
77import vtkWebGPUSampler from 'vtk.js/Sources/Rendering/WebGPU/Sampler' ;
88import { InterpolationType } from 'vtk.js/Sources/Rendering/Core/ImageProperty/Constants' ;
99import { ProjectionMode } from 'vtk.js/Sources/Rendering/Core/ImageCPRMapper/Constants' ;
10+ import { Resolve } from 'vtk.js/Sources/Rendering/Core/Mapper/CoincidentTopologyHelper' ;
1011import { registerOverride } from 'vtk.js/Sources/Rendering/WebGPU/ViewNodeFactory' ;
1112
1213const { BufferUsage } = vtkWebGPUBufferManager ;
@@ -41,6 +42,8 @@ const cprFragTemplate = `
4142
4243//VTK::Clip::Dec
4344
45+ //VTK::Coincident::Dec
46+
4447//VTK::RenderEncoder::Dec
4548
4649//VTK::IOStructs::Dec
@@ -152,11 +155,15 @@ fn main(
152155{
153156 var output : fragmentOutput;
154157
155- let interpolatedOrientation = quaternionLerpOrSlerp(
156- input.centerlineBotOrientationVS,
157- input.centerlineTopOrientationVS,
158- input.quadOffsetVS.y
159- );
158+ var interpolatedOrientation = mapperUBO.UniformOrientation;
159+ if (mapperUBO.UseUniformOrientation == 0u)
160+ {
161+ interpolatedOrientation = quaternionLerpOrSlerp(
162+ input.centerlineBottomOrientationVS,
163+ input.centerlineTopOrientationVS,
164+ input.quadOffsetVS.y
165+ );
166+ }
160167 let samplingDirection = applyQuaternionToVec(
161168 interpolatedOrientation,
162169 mapperUBO.TangentDirection.xyz
@@ -264,13 +271,16 @@ fn main(
264271 }
265272
266273 //VTK::Select::Impl
274+ //VTK::Coincident::Impl
267275 //VTK::RenderEncoder::Impl
268276 return output;
269277}
270278` ;
271279
272280const tmpMat4 = new Float64Array ( 16 ) ;
273281const tmp2Mat4 = new Float64Array ( 16 ) ;
282+ const DEFAULT_ORIENTATION = [ 0 , 0 , 0 , 1 ] ;
283+ const QUAD_VERTEX_ORDER = [ 0 , 1 , 3 , 0 , 3 , 2 ] ;
274284
275285function computeFnToString ( property , fn , numberOfComponents ) {
276286 const pwfun = fn . apply ( property ) ;
@@ -284,6 +294,15 @@ function computeFnToString(property, fn, numberOfComponents) {
284294function vtkWebGPUImageCPRMapper ( publicAPI , model ) {
285295 model . classHierarchy . push ( 'vtkWebGPUImageCPRMapper' ) ;
286296
297+ publicAPI . getCoincidentParameters = ( ) => {
298+ if (
299+ model . renderable . getResolveCoincidentTopology ( ) === Resolve . PolygonOffset
300+ ) {
301+ return model . renderable . getCoincidentTopologyPolygonOffsetParameters ( ) ;
302+ }
303+ return null ;
304+ } ;
305+
287306 publicAPI . buildPass = ( prepass ) => {
288307 if ( prepass ) {
289308 model . WebGPUImageSlice = publicAPI . getFirstAncestorOfType (
@@ -327,7 +346,8 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
327346 model . renderable . getNumberOfClippingPlanes ( ) ,
328347 MAX_CLIPPING_PLANES
329348 ) ;
330- model . pipelineHash = `cprcp${ numClipPlanes } ${ model . renderEncoder . getPipelineHash ( ) } ` ;
349+ const useCoincident = publicAPI . getCoincidentParameters ( ) ? 1 : 0 ;
350+ model . pipelineHash = `cprcp${ numClipPlanes } co${ useCoincident } ${ model . renderEncoder . getPipelineHash ( ) } ` ;
331351 } ;
332352
333353 publicAPI . updateGeometry = ( ) => {
@@ -351,35 +371,46 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
351371 const centerlinePositions = new Float32Array ( numVerts * 3 ) ;
352372 const quadIndices = new Float32Array ( numVerts ) ;
353373 const topOrientations = new Float32Array ( numVerts * 4 ) ;
354- const botOrientations = new Float32Array ( numVerts * 4 ) ;
374+ const bottomOrientations = new Float32Array ( numVerts * 4 ) ;
355375
356376 const pa = [ 0 , 0 , 0 ] ;
357377 const pb = [ 0 , 0 , 0 ] ;
358- const vertexOrder = [ 0 , 1 , 3 , 0 , 3 , 2 ] ;
359378
360379 for ( let lineIdx = 0 ; lineIdx < nLines ; ++ lineIdx ) {
361380 pointsDataArray . getPoint ( lineIdx , pa ) ;
362381 pointsDataArray . getPoint ( lineIdx + 1 , pb ) ;
363382
364- const quadPoints = [
365- [ 0 , height - distances [ lineIdx ] , 0 ] ,
366- [ widthMC , height - distances [ lineIdx ] , 0 ] ,
367- [ 0 , height - distances [ lineIdx + 1 ] , 0 ] ,
368- [ widthMC , height - distances [ lineIdx + 1 ] , 0 ] ,
369- ] ;
370- const quadCenterline = [ pa , pa , pb , pb ] ;
371- const topQuat = orientationQuats [ lineIdx ] ?? [ 0 , 0 , 0 , 1 ] ;
372- const botQuat = orientationQuats [ lineIdx + 1 ] ?? topQuat ;
383+ const topY = height - distances [ lineIdx ] ;
384+ const bottomY = height - distances [ lineIdx + 1 ] ;
385+ const topQuat = orientationQuats [ lineIdx ] ?? DEFAULT_ORIENTATION ;
386+ const bottomQuat = orientationQuats [ lineIdx + 1 ] ?? topQuat ;
373387
374388 for ( let localIdx = 0 ; localIdx < 6 ; ++ localIdx ) {
375- const quadIdx = vertexOrder [ localIdx ] ;
389+ const quadIdx = QUAD_VERTEX_ORDER [ localIdx ] ;
376390 const vertIdx = lineIdx * 6 + localIdx ;
391+ const posOffset = vertIdx * 3 ;
392+ const orientationOffset = vertIdx * 4 ;
393+
394+ positions [ posOffset ] = quadIdx === 1 || quadIdx === 3 ? widthMC : 0.0 ;
395+ positions [ posOffset + 1 ] = quadIdx > 1 ? bottomY : topY ;
396+ positions [ posOffset + 2 ] = 0.0 ;
397+
398+ const centerPoint = quadIdx > 1 ? pb : pa ;
399+ centerlinePositions [ posOffset ] = centerPoint [ 0 ] ;
400+ centerlinePositions [ posOffset + 1 ] = centerPoint [ 1 ] ;
401+ centerlinePositions [ posOffset + 2 ] = centerPoint [ 2 ] ;
377402
378- positions . set ( quadPoints [ quadIdx ] , vertIdx * 3 ) ;
379- centerlinePositions . set ( quadCenterline [ quadIdx ] , vertIdx * 3 ) ;
380403 quadIndices [ vertIdx ] = quadIdx ;
381- topOrientations . set ( topQuat , vertIdx * 4 ) ;
382- botOrientations . set ( botQuat , vertIdx * 4 ) ;
404+
405+ topOrientations [ orientationOffset ] = topQuat [ 0 ] ;
406+ topOrientations [ orientationOffset + 1 ] = topQuat [ 1 ] ;
407+ topOrientations [ orientationOffset + 2 ] = topQuat [ 2 ] ;
408+ topOrientations [ orientationOffset + 3 ] = topQuat [ 3 ] ;
409+
410+ bottomOrientations [ orientationOffset ] = bottomQuat [ 0 ] ;
411+ bottomOrientations [ orientationOffset + 1 ] = bottomQuat [ 1 ] ;
412+ bottomOrientations [ orientationOffset + 2 ] = bottomQuat [ 2 ] ;
413+ bottomOrientations [ orientationOffset + 3 ] = bottomQuat [ 3 ] ;
383414 }
384415 }
385416
@@ -394,7 +425,7 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
394425 const centerlineHash = `cpr-centerline-${ mtime } ` ;
395426 const quadHash = `cpr-quad-${ mtime } ` ;
396427 const topHash = `cpr-top-${ mtime } ` ;
397- const botHash = `cpr-bot -${ mtime } ` ;
428+ const bottomHash = `cpr-bottom -${ mtime } ` ;
398429
399430 const requests = [
400431 [ vertexHash , positions , 'float32x3' , [ 'vertexMC' ] ] ,
@@ -406,7 +437,12 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
406437 ] ,
407438 [ quadHash , quadIndices , 'float32' , [ 'quadIndex' ] ] ,
408439 [ topHash , topOrientations , 'float32x4' , [ 'centerlineTopOrientation' ] ] ,
409- [ botHash , botOrientations , 'float32x4' , [ 'centerlineBotOrientation' ] ] ,
440+ [
441+ bottomHash ,
442+ bottomOrientations ,
443+ 'float32x4' ,
444+ [ 'centerlineBottomOrientation' ] ,
445+ ] ,
410446 ] ;
411447
412448 requests . forEach ( ( [ hash , nativeArray , format , names ] ) => {
@@ -612,6 +648,14 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
612648 ...model . renderable . getBitangentDirection ( ) ,
613649 0.0 ,
614650 ] ) ;
651+ model . UBO . setArray (
652+ 'UniformOrientation' ,
653+ model . renderable . getUniformOrientation ( )
654+ ) ;
655+ model . UBO . setValue (
656+ 'UseUniformOrientation' ,
657+ model . renderable . getUseUniformOrientation ( ) ? 1 : 0
658+ ) ;
615659 model . UBO . setValue ( 'Width' , model . renderable . getWidth ( ) ) ;
616660 model . UBO . setValue ( 'Opacity' , property . getOpacity ( ) ) ;
617661 model . UBO . setValue ( 'PropID' , model . WebGPUImageSlice . getPropID ( ) ) ;
@@ -634,6 +678,13 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
634678 model . UBO . setArray ( `ClipPlane${ i } ` , clipPlane ) ;
635679 }
636680
681+ const coincidentParameters = publicAPI . getCoincidentParameters ( ) ;
682+ model . UBO . setValue ( 'CoincidentFactor' , coincidentParameters ?. factor ?? 0.0 ) ;
683+ model . UBO . setValue (
684+ 'CoincidentOffset' ,
685+ 0.000016 * ( coincidentParameters ?. offset ?? 0.0 )
686+ ) ;
687+
637688 const projectionSamples =
638689 model . renderable . getProjectionSlabNumberOfSamples ( ) ;
639690 const projectionThickness = model . renderable . getProjectionSlabThickness ( ) ;
@@ -730,7 +781,7 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
730781 vDesc . addOutput ( 'vec2<f32>' , 'quadOffsetVS' ) ;
731782 vDesc . addOutput ( 'vec3<f32>' , 'centerlinePosVS' ) ;
732783 vDesc . addOutput ( 'vec4<f32>' , 'centerlineTopOrientationVS' ) ;
733- vDesc . addOutput ( 'vec4<f32>' , 'centerlineBotOrientationVS ' ) ;
784+ vDesc . addOutput ( 'vec4<f32>' , 'centerlineBottomOrientationVS ' ) ;
734785
735786 let code = vDesc . getCode ( ) ;
736787 code = vtkWebGPUShaderCache . substitute ( code , '//VTK::ImageCPR::Impl' , [
@@ -742,7 +793,7 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
742793 ');' ,
743794 'output.centerlinePosVS = centerlinePosition;' ,
744795 'output.centerlineTopOrientationVS = centerlineTopOrientation;' ,
745- 'output.centerlineBotOrientationVS = centerlineBotOrientation ;' ,
796+ 'output.centerlineBottomOrientationVS = centerlineBottomOrientation ;' ,
746797 'let posSC = mapperUBO.BCSCMatrix * vec4<f32>(vertexMC, 1.0);' ,
747798 'output.Position = rendererUBO.SCPCMatrix * posSC;' ,
748799 ] ) . result ;
@@ -789,6 +840,51 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
789840 publicAPI . replaceShaderClip
790841 ) ;
791842
843+ publicAPI . replaceShaderCoincident = ( hash , pipeline ) => {
844+ const fDesc = pipeline . getShaderDescription ( 'fragment' ) ;
845+ let code = fDesc . getCode ( ) ;
846+ const coincidentParameters = publicAPI . getCoincidentParameters ( ) ;
847+
848+ if (
849+ ! coincidentParameters ||
850+ ( coincidentParameters . factor === 0.0 &&
851+ coincidentParameters . offset === 0.0 )
852+ ) {
853+ code = vtkWebGPUShaderCache . substitute (
854+ code ,
855+ '//VTK::Coincident::Dec' ,
856+ [ ]
857+ ) . result ;
858+ code = vtkWebGPUShaderCache . substitute (
859+ code ,
860+ '//VTK::Coincident::Impl' ,
861+ [ ]
862+ ) . result ;
863+ fDesc . setCode ( code ) ;
864+ return ;
865+ }
866+
867+ fDesc . addBuiltinInput ( 'vec4<f32>' , '@builtin(position) fragPos' ) ;
868+ fDesc . addBuiltinOutput ( 'f32' , '@builtin(frag_depth) fragDepth' ) ;
869+ code = vtkWebGPUShaderCache . substitute (
870+ code ,
871+ '//VTK::Coincident::Dec' ,
872+ [ ]
873+ ) . result ;
874+ code = vtkWebGPUShaderCache . substitute ( code , '//VTK::Coincident::Impl' , [
875+ 'output.fragDepth = clamp(' ,
876+ ' input.fragPos.z + mapperUBO.CoincidentOffset,' ,
877+ ' 0.0,' ,
878+ ' 1.0' ,
879+ ');' ,
880+ ] ) . result ;
881+ fDesc . setCode ( code ) ;
882+ } ;
883+ model . shaderReplacements . set (
884+ 'replaceShaderCoincident' ,
885+ publicAPI . replaceShaderCoincident
886+ ) ;
887+
792888 publicAPI . replaceShaderRenderEncoder = ( hash , pipeline ) => {
793889 if ( hash . includes ( 'sel' ) ) {
794890 const fDesc = pipeline . getShaderDescription ( 'fragment' ) ;
@@ -833,6 +929,7 @@ export function extend(publicAPI, model, initialValues = {}) {
833929 model . UBO . addEntry ( 'BackgroundColor' , 'vec4<f32>' ) ;
834930 model . UBO . addEntry ( 'VolumeSizeMC' , 'vec4<f32>' ) ;
835931 model . UBO . addEntry ( 'GlobalCenterPoint' , 'vec4<f32>' ) ;
932+ model . UBO . addEntry ( 'UniformOrientation' , 'vec4<f32>' ) ;
836933 model . UBO . addEntry ( 'TangentDirection' , 'vec4<f32>' ) ;
837934 model . UBO . addEntry ( 'BitangentDirection' , 'vec4<f32>' ) ;
838935 model . UBO . addEntry ( 'ComponentMix' , 'vec4<f32>' ) ;
@@ -849,12 +946,15 @@ export function extend(publicAPI, model, initialValues = {}) {
849946 model . UBO . addEntry ( 'ClipPlane5' , 'vec4<f32>' ) ;
850947 model . UBO . addEntry ( 'Width' , 'f32' ) ;
851948 model . UBO . addEntry ( 'Opacity' , 'f32' ) ;
949+ model . UBO . addEntry ( 'CoincidentFactor' , 'f32' ) ;
950+ model . UBO . addEntry ( 'CoincidentOffset' , 'f32' ) ;
852951 model . UBO . addEntry ( 'PropID' , 'u32' ) ;
853952 model . UBO . addEntry ( 'NumClipPlanes' , 'u32' ) ;
854953 model . UBO . addEntry ( 'ProjectionSamples' , 'u32' ) ;
855954 model . UBO . addEntry ( 'ProjectionMode' , 'u32' ) ;
856955 model . UBO . addEntry ( 'NumComponents' , 'u32' ) ;
857956 model . UBO . addEntry ( 'IndependentComponents' , 'u32' ) ;
957+ model . UBO . addEntry ( 'UseUniformOrientation' , 'u32' ) ;
858958 model . UBO . addEntry ( 'UseCenterPoint' , 'u32' ) ;
859959
860960 vtkWebGPUImageCPRMapper ( publicAPI , model ) ;
0 commit comments