@@ -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,10 @@ 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 =
351+ `cprcp${ numClipPlanes } co${ useCoincident } ` +
352+ model . renderEncoder . getPipelineHash ( ) ;
331353 } ;
332354
333355 publicAPI . updateGeometry = ( ) => {
@@ -351,35 +373,46 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
351373 const centerlinePositions = new Float32Array ( numVerts * 3 ) ;
352374 const quadIndices = new Float32Array ( numVerts ) ;
353375 const topOrientations = new Float32Array ( numVerts * 4 ) ;
354- const botOrientations = new Float32Array ( numVerts * 4 ) ;
376+ const bottomOrientations = new Float32Array ( numVerts * 4 ) ;
355377
356378 const pa = [ 0 , 0 , 0 ] ;
357379 const pb = [ 0 , 0 , 0 ] ;
358- const vertexOrder = [ 0 , 1 , 3 , 0 , 3 , 2 ] ;
359380
360381 for ( let lineIdx = 0 ; lineIdx < nLines ; ++ lineIdx ) {
361382 pointsDataArray . getPoint ( lineIdx , pa ) ;
362383 pointsDataArray . getPoint ( lineIdx + 1 , pb ) ;
363384
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 ;
385+ const topY = height - distances [ lineIdx ] ;
386+ const bottomY = height - distances [ lineIdx + 1 ] ;
387+ const topQuat = orientationQuats [ lineIdx ] ?? DEFAULT_ORIENTATION ;
388+ const bottomQuat = orientationQuats [ lineIdx + 1 ] ?? topQuat ;
373389
374390 for ( let localIdx = 0 ; localIdx < 6 ; ++ localIdx ) {
375- const quadIdx = vertexOrder [ localIdx ] ;
391+ const quadIdx = QUAD_VERTEX_ORDER [ localIdx ] ;
376392 const vertIdx = lineIdx * 6 + localIdx ;
393+ const posOffset = vertIdx * 3 ;
394+ const orientationOffset = vertIdx * 4 ;
395+
396+ positions [ posOffset ] = quadIdx & 1 ? widthMC : 0.0 ;
397+ positions [ posOffset + 1 ] = quadIdx > 1 ? bottomY : topY ;
398+ positions [ posOffset + 2 ] = 0.0 ;
399+
400+ const centerPoint = quadIdx > 1 ? pb : pa ;
401+ centerlinePositions [ posOffset ] = centerPoint [ 0 ] ;
402+ centerlinePositions [ posOffset + 1 ] = centerPoint [ 1 ] ;
403+ centerlinePositions [ posOffset + 2 ] = centerPoint [ 2 ] ;
377404
378- positions . set ( quadPoints [ quadIdx ] , vertIdx * 3 ) ;
379- centerlinePositions . set ( quadCenterline [ quadIdx ] , vertIdx * 3 ) ;
380405 quadIndices [ vertIdx ] = quadIdx ;
381- topOrientations . set ( topQuat , vertIdx * 4 ) ;
382- botOrientations . set ( botQuat , vertIdx * 4 ) ;
406+
407+ topOrientations [ orientationOffset ] = topQuat [ 0 ] ;
408+ topOrientations [ orientationOffset + 1 ] = topQuat [ 1 ] ;
409+ topOrientations [ orientationOffset + 2 ] = topQuat [ 2 ] ;
410+ topOrientations [ orientationOffset + 3 ] = topQuat [ 3 ] ;
411+
412+ bottomOrientations [ orientationOffset ] = bottomQuat [ 0 ] ;
413+ bottomOrientations [ orientationOffset + 1 ] = bottomQuat [ 1 ] ;
414+ bottomOrientations [ orientationOffset + 2 ] = bottomQuat [ 2 ] ;
415+ bottomOrientations [ orientationOffset + 3 ] = bottomQuat [ 3 ] ;
383416 }
384417 }
385418
@@ -394,7 +427,7 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
394427 const centerlineHash = `cpr-centerline-${ mtime } ` ;
395428 const quadHash = `cpr-quad-${ mtime } ` ;
396429 const topHash = `cpr-top-${ mtime } ` ;
397- const botHash = `cpr-bot -${ mtime } ` ;
430+ const bottomHash = `cpr-bottom -${ mtime } ` ;
398431
399432 const requests = [
400433 [ vertexHash , positions , 'float32x3' , [ 'vertexMC' ] ] ,
@@ -406,7 +439,12 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
406439 ] ,
407440 [ quadHash , quadIndices , 'float32' , [ 'quadIndex' ] ] ,
408441 [ topHash , topOrientations , 'float32x4' , [ 'centerlineTopOrientation' ] ] ,
409- [ botHash , botOrientations , 'float32x4' , [ 'centerlineBotOrientation' ] ] ,
442+ [
443+ bottomHash ,
444+ bottomOrientations ,
445+ 'float32x4' ,
446+ [ 'centerlineBottomOrientation' ] ,
447+ ] ,
410448 ] ;
411449
412450 requests . forEach ( ( [ hash , nativeArray , format , names ] ) => {
@@ -612,6 +650,14 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
612650 ...model . renderable . getBitangentDirection ( ) ,
613651 0.0 ,
614652 ] ) ;
653+ model . UBO . setArray (
654+ 'UniformOrientation' ,
655+ model . renderable . getUniformOrientation ( )
656+ ) ;
657+ model . UBO . setValue (
658+ 'UseUniformOrientation' ,
659+ model . renderable . getUseUniformOrientation ( ) ? 1 : 0
660+ ) ;
615661 model . UBO . setValue ( 'Width' , model . renderable . getWidth ( ) ) ;
616662 model . UBO . setValue ( 'Opacity' , property . getOpacity ( ) ) ;
617663 model . UBO . setValue ( 'PropID' , model . WebGPUImageSlice . getPropID ( ) ) ;
@@ -634,6 +680,13 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
634680 model . UBO . setArray ( `ClipPlane${ i } ` , clipPlane ) ;
635681 }
636682
683+ const coincidentParameters = publicAPI . getCoincidentParameters ( ) ;
684+ model . UBO . setValue ( 'CoincidentFactor' , coincidentParameters ?. factor ?? 0.0 ) ;
685+ model . UBO . setValue (
686+ 'CoincidentOffset' ,
687+ 0.000016 * ( coincidentParameters ?. offset ?? 0.0 )
688+ ) ;
689+
637690 const projectionSamples =
638691 model . renderable . getProjectionSlabNumberOfSamples ( ) ;
639692 const projectionThickness = model . renderable . getProjectionSlabThickness ( ) ;
@@ -730,7 +783,7 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
730783 vDesc . addOutput ( 'vec2<f32>' , 'quadOffsetVS' ) ;
731784 vDesc . addOutput ( 'vec3<f32>' , 'centerlinePosVS' ) ;
732785 vDesc . addOutput ( 'vec4<f32>' , 'centerlineTopOrientationVS' ) ;
733- vDesc . addOutput ( 'vec4<f32>' , 'centerlineBotOrientationVS ' ) ;
786+ vDesc . addOutput ( 'vec4<f32>' , 'centerlineBottomOrientationVS ' ) ;
734787
735788 let code = vDesc . getCode ( ) ;
736789 code = vtkWebGPUShaderCache . substitute ( code , '//VTK::ImageCPR::Impl' , [
@@ -742,7 +795,7 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
742795 ');' ,
743796 'output.centerlinePosVS = centerlinePosition;' ,
744797 'output.centerlineTopOrientationVS = centerlineTopOrientation;' ,
745- 'output.centerlineBotOrientationVS = centerlineBotOrientation ;' ,
798+ 'output.centerlineBottomOrientationVS = centerlineBottomOrientation ;' ,
746799 'let posSC = mapperUBO.BCSCMatrix * vec4<f32>(vertexMC, 1.0);' ,
747800 'output.Position = rendererUBO.SCPCMatrix * posSC;' ,
748801 ] ) . result ;
@@ -789,6 +842,51 @@ function vtkWebGPUImageCPRMapper(publicAPI, model) {
789842 publicAPI . replaceShaderClip
790843 ) ;
791844
845+ publicAPI . replaceShaderCoincident = ( hash , pipeline ) => {
846+ const fDesc = pipeline . getShaderDescription ( 'fragment' ) ;
847+ let code = fDesc . getCode ( ) ;
848+ const coincidentParameters = publicAPI . getCoincidentParameters ( ) ;
849+
850+ if (
851+ ! coincidentParameters ||
852+ ( coincidentParameters . factor === 0.0 &&
853+ coincidentParameters . offset === 0.0 )
854+ ) {
855+ code = vtkWebGPUShaderCache . substitute (
856+ code ,
857+ '//VTK::Coincident::Dec' ,
858+ [ ]
859+ ) . result ;
860+ code = vtkWebGPUShaderCache . substitute (
861+ code ,
862+ '//VTK::Coincident::Impl' ,
863+ [ ]
864+ ) . result ;
865+ fDesc . setCode ( code ) ;
866+ return ;
867+ }
868+
869+ fDesc . addBuiltinInput ( 'vec4<f32>' , '@builtin(position) fragPos' ) ;
870+ fDesc . addBuiltinOutput ( 'f32' , '@builtin(frag_depth) fragDepth' ) ;
871+ code = vtkWebGPUShaderCache . substitute (
872+ code ,
873+ '//VTK::Coincident::Dec' ,
874+ [ ]
875+ ) . result ;
876+ code = vtkWebGPUShaderCache . substitute ( code , '//VTK::Coincident::Impl' , [
877+ 'output.fragDepth = clamp(' ,
878+ ' input.fragPos.z + mapperUBO.CoincidentOffset,' ,
879+ ' 0.0,' ,
880+ ' 1.0' ,
881+ ');' ,
882+ ] ) . result ;
883+ fDesc . setCode ( code ) ;
884+ } ;
885+ model . shaderReplacements . set (
886+ 'replaceShaderCoincident' ,
887+ publicAPI . replaceShaderCoincident
888+ ) ;
889+
792890 publicAPI . replaceShaderRenderEncoder = ( hash , pipeline ) => {
793891 if ( hash . includes ( 'sel' ) ) {
794892 const fDesc = pipeline . getShaderDescription ( 'fragment' ) ;
@@ -833,6 +931,7 @@ export function extend(publicAPI, model, initialValues = {}) {
833931 model . UBO . addEntry ( 'BackgroundColor' , 'vec4<f32>' ) ;
834932 model . UBO . addEntry ( 'VolumeSizeMC' , 'vec4<f32>' ) ;
835933 model . UBO . addEntry ( 'GlobalCenterPoint' , 'vec4<f32>' ) ;
934+ model . UBO . addEntry ( 'UniformOrientation' , 'vec4<f32>' ) ;
836935 model . UBO . addEntry ( 'TangentDirection' , 'vec4<f32>' ) ;
837936 model . UBO . addEntry ( 'BitangentDirection' , 'vec4<f32>' ) ;
838937 model . UBO . addEntry ( 'ComponentMix' , 'vec4<f32>' ) ;
@@ -849,12 +948,15 @@ export function extend(publicAPI, model, initialValues = {}) {
849948 model . UBO . addEntry ( 'ClipPlane5' , 'vec4<f32>' ) ;
850949 model . UBO . addEntry ( 'Width' , 'f32' ) ;
851950 model . UBO . addEntry ( 'Opacity' , 'f32' ) ;
951+ model . UBO . addEntry ( 'CoincidentFactor' , 'f32' ) ;
952+ model . UBO . addEntry ( 'CoincidentOffset' , 'f32' ) ;
852953 model . UBO . addEntry ( 'PropID' , 'u32' ) ;
853954 model . UBO . addEntry ( 'NumClipPlanes' , 'u32' ) ;
854955 model . UBO . addEntry ( 'ProjectionSamples' , 'u32' ) ;
855956 model . UBO . addEntry ( 'ProjectionMode' , 'u32' ) ;
856957 model . UBO . addEntry ( 'NumComponents' , 'u32' ) ;
857958 model . UBO . addEntry ( 'IndependentComponents' , 'u32' ) ;
959+ model . UBO . addEntry ( 'UseUniformOrientation' , 'u32' ) ;
858960 model . UBO . addEntry ( 'UseCenterPoint' , 'u32' ) ;
859961
860962 vtkWebGPUImageCPRMapper ( publicAPI , model ) ;
0 commit comments