@kitware/vtk.js 21.6.1 → 22.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/Common/Core/CellArray.js +2 -2
  2. package/Common/Core/DataArray.js +2 -2
  3. package/Common/Core/MatrixBuilder.d.ts +1 -1
  4. package/Common/Core/ScalarsToColors.js +12 -11
  5. package/Common/DataModel/BoundingBox.js +2 -2
  6. package/Common/DataModel/Box.js +2 -2
  7. package/Common/DataModel/CellTypes.js +2 -2
  8. package/Common/DataModel/Cylinder.js +2 -2
  9. package/Common/DataModel/DataSet.js +2 -2
  10. package/Common/DataModel/DataSetAttributes.js +2 -2
  11. package/Common/DataModel/ImplicitBoolean.js +2 -2
  12. package/Common/DataModel/Line.js +2 -2
  13. package/Common/DataModel/PiecewiseFunction.js +3 -3
  14. package/Common/DataModel/Plane.js +2 -2
  15. package/Common/DataModel/SelectionNode.js +2 -2
  16. package/Common/DataModel/Sphere.js +2 -2
  17. package/Common/DataModel/StructuredData.js +2 -2
  18. package/Common/DataModel/Triangle.js +2 -2
  19. package/Common/Transform/LandmarkTransform.js +2 -2
  20. package/Filters/Core/Cutter.js +2 -2
  21. package/Filters/General/Calculator.js +2 -2
  22. package/Filters/Sources/Arrow2DSource.js +2 -2
  23. package/Filters/Sources/CircleSource.js +2 -2
  24. package/IO/Core/DataAccessHelper/HtmlDataAccessHelper.js +6 -12
  25. package/IO/Core/DataAccessHelper/HttpDataAccessHelper.js +11 -19
  26. package/IO/Core/DataAccessHelper/JSZipDataAccessHelper.js +8 -15
  27. package/IO/Core/DataAccessHelper/LiteHttpDataAccessHelper.js +11 -19
  28. package/IO/Core/HttpSceneLoader.js +2 -2
  29. package/IO/Core/ImageStream/DefaultProtocol.js +2 -6
  30. package/IO/Geometry/PLYWriter/Constants.js +19 -0
  31. package/IO/Geometry/PLYWriter.d.ts +203 -0
  32. package/IO/Geometry/PLYWriter.js +323 -0
  33. package/IO/Geometry/STLWriter.js +2 -2
  34. package/IO/Geometry.js +3 -1
  35. package/IO/XML/XMLImageDataWriter.js +2 -2
  36. package/IO/XML/XMLPolyDataWriter.js +2 -2
  37. package/Imaging/Core/AbstractImageInterpolator/InterpolationInfo.js +2 -2
  38. package/Imaging/Core/AbstractImageInterpolator.js +2 -2
  39. package/Imaging/Core/ImageInterpolator.js +12 -12
  40. package/Imaging/Core/ImageReslice.js +10 -10
  41. package/Imaging/Hybrid/SampleFunction.js +2 -2
  42. package/Interaction/Animations/TimeStepBasedAnimationHandler.js +2 -2
  43. package/Interaction/Manipulators/MouseBoxSelectorManipulator.js +2 -2
  44. package/Interaction/Style/InteractorStyleManipulator.js +2 -2
  45. package/Interaction/Style/InteractorStyleRemoteMouse.js +2 -2
  46. package/Interaction/UI/FPSMonitor.js +2 -2
  47. package/Interaction/UI/Slider.js +2 -2
  48. package/Interaction/Widgets/AbstractWidget.js +2 -2
  49. package/Interaction/Widgets/DistanceRepresentation.js +2 -2
  50. package/Interaction/Widgets/DistanceWidget.js +2 -2
  51. package/Interaction/Widgets/HandleRepresentation.js +2 -2
  52. package/Interaction/Widgets/HandleWidget.js +2 -2
  53. package/Interaction/Widgets/ImageCroppingRegionsWidget.js +2 -2
  54. package/Interaction/Widgets/LabelRepresentation.js +2 -2
  55. package/Interaction/Widgets/LabelWidget.js +2 -2
  56. package/Interaction/Widgets/LineRepresentation.js +2 -2
  57. package/Interaction/Widgets/LineWidget.js +2 -2
  58. package/Interaction/Widgets/OrientationMarkerWidget.js +2 -2
  59. package/Interaction/Widgets/PiecewiseGaussianWidget.js +2 -2
  60. package/Interaction/Widgets/ResliceCursor/ResliceCursor.js +2 -2
  61. package/Interaction/Widgets/ResliceCursor/ResliceCursorActor.js +2 -2
  62. package/Interaction/Widgets/ResliceCursor/ResliceCursorPolyDataAlgorithm.js +2 -2
  63. package/Interaction/Widgets/ResliceCursor/ResliceCursorWidget.js +2 -2
  64. package/Interaction/Widgets/SphereHandleRepresentation.js +2 -2
  65. package/Proxy/Core/PiecewiseFunctionProxy.js +2 -2
  66. package/Proxy/Core/ProxyManager/core.js +2 -2
  67. package/Proxy/Core/ProxyManager/properties.js +2 -2
  68. package/Proxy/Core/ProxyManager/state.js +2 -2
  69. package/Proxy/Representations/SliceRepresentationProxy.js +2 -2
  70. package/Rendering/Core/AbstractMapper.d.ts +4 -4
  71. package/Rendering/Core/AbstractMapper.js +18 -7
  72. package/Rendering/Core/Actor.js +2 -2
  73. package/Rendering/Core/AnnotatedCubeActor.js +2 -2
  74. package/Rendering/Core/AxesActor.js +2 -2
  75. package/Rendering/Core/CellPicker.js +2 -2
  76. package/Rendering/Core/ColorTransferFunction.js +2 -2
  77. package/Rendering/Core/Coordinate.js +2 -2
  78. package/Rendering/Core/CubeAxesActor.js +2 -2
  79. package/Rendering/Core/Follower.js +2 -2
  80. package/Rendering/Core/Glyph3DMapper.js +2 -2
  81. package/Rendering/Core/ImageMapper.js +2 -2
  82. package/Rendering/Core/InteractorObserver.js +2 -2
  83. package/Rendering/Core/InteractorStyle.js +2 -2
  84. package/Rendering/Core/Mapper.js +2 -2
  85. package/Rendering/Core/Picker.js +2 -2
  86. package/Rendering/Core/Property.js +2 -2
  87. package/Rendering/Core/RenderWindowInteractor.js +36 -14
  88. package/Rendering/Core/ScalarBarActor.js +2 -2
  89. package/Rendering/Core/VolumeMapper.js +1 -4
  90. package/Rendering/Core/VolumeProperty.js +2 -2
  91. package/Rendering/Core.js +2 -2
  92. package/Rendering/Misc/RenderWindowWithControlBar.js +2 -2
  93. package/Rendering/Misc/SynchronizableRenderWindow/vtkObjectManager.js +2 -2
  94. package/Rendering/Misc/SynchronizableRenderWindow.js +2 -2
  95. package/Rendering/OpenGL/BufferObject.js +5 -5
  96. package/Rendering/OpenGL/CellArrayBufferObject.js +2 -1
  97. package/Rendering/OpenGL/Glyph3DMapper.js +2 -2
  98. package/Rendering/OpenGL/HardwareSelector.js +2 -2
  99. package/Rendering/OpenGL/RenderWindow.js +1 -1
  100. package/Rendering/OpenGL/SphereMapper.js +2 -2
  101. package/Rendering/OpenGL/StickMapper.js +2 -2
  102. package/Rendering/OpenGL/SurfaceLIC/SurfaceLICMapper.js +2 -2
  103. package/Rendering/OpenGL/Texture.js +2 -2
  104. package/Rendering/OpenGL/VolumeMapper.js +11 -18
  105. package/Rendering/WebGPU/Buffer.js +2 -2
  106. package/Rendering/WebGPU/BufferManager.js +2 -2
  107. package/Rendering/WebGPU/Glyph3DMapper.js +2 -2
  108. package/Rendering/WebGPU/HardwareSelector.js +1 -1
  109. package/Rendering/WebGPU/MapperHelper.js +2 -1
  110. package/Rendering/WebGPU/PolyDataMapper.js +1 -1
  111. package/Rendering/WebGPU/TextureManager.js +1 -1
  112. package/Rendering/WebGPU/VolumePass.js +366 -64
  113. package/Rendering/WebGPU/VolumePassFSQ.js +5 -2
  114. package/Widgets/Core/AbstractWidgetFactory.js +2 -2
  115. package/Widgets/Representations/ArrowHandleRepresentation.js +2 -2
  116. package/Widgets/Representations/ContextRepresentation.js +2 -2
  117. package/Widgets/Representations/HandleRepresentation.js +2 -2
  118. package/Widgets/Representations/PolyLineRepresentation.js +2 -2
  119. package/Widgets/Representations/ResliceCursorContextRepresentation.js +2 -2
  120. package/Widgets/SVG/SVGLandmarkRepresentation.js +2 -2
  121. package/Widgets/Widgets3D/EllipseWidget/behavior.js +2 -2
  122. package/Widgets/Widgets3D/EllipseWidget.js +2 -2
  123. package/Widgets/Widgets3D/InteractiveOrientationWidget/behavior.js +2 -2
  124. package/Widgets/Widgets3D/LineWidget/behavior.js +2 -2
  125. package/Widgets/Widgets3D/RectangleWidget/behavior.js +2 -2
  126. package/Widgets/Widgets3D/RectangleWidget.js +2 -2
  127. package/Widgets/Widgets3D/ShapeWidget/behavior.js +2 -2
  128. package/Widgets/Widgets3D/ShapeWidget.js +2 -2
  129. package/_virtual/rollup-plugin-worker-loader__module_Sources/Filters/General/PaintFilter/PaintFilter.worker.js +44 -44
  130. package/_virtual/rollup-plugin-worker-loader__module_Sources/Interaction/Widgets/PiecewiseGaussianWidget/ComputeHistogram.worker.js +1 -1
  131. package/macros.js +16 -32
  132. package/package.json +52 -54
  133. package/vtk.js +2 -2
  134. package/Utilities/config/rules-linter.js +0 -13
@@ -6,9 +6,9 @@ import vtkWebGPUTypes from './Types.js';
6
6
  import vtkProperty from '../Core/Property.js';
7
7
  import Constants from './BufferManager/Constants.js';
8
8
 
9
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
9
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
10
10
 
11
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
11
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
12
12
  var BufferUsage = Constants.BufferUsage,
13
13
  PrimitiveTypes = Constants.PrimitiveTypes;
14
14
  var Representation = vtkProperty.Representation;
@@ -6,9 +6,9 @@ import vtkWebGPUShaderCache from './ShaderCache.js';
6
6
  import vtkWebGPUBufferManager from './BufferManager.js';
7
7
  import { registerOverride } from './ViewNodeFactory.js';
8
8
 
9
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
9
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
10
10
 
11
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
11
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
12
12
  var PrimitiveTypes = vtkWebGPUBufferManager.PrimitiveTypes; // ----------------------------------------------------------------------------
13
13
  // vtkWebGPUSphereMapper methods
14
14
  // ----------------------------------------------------------------------------
@@ -247,7 +247,7 @@ function vtkWebGPUHardwareSelector(publicAPI, model) {
247
247
  model.WebGPURenderWindow.initialize();
248
248
  _context.next = 8;
249
249
  return new Promise(function (resolve) {
250
- return model.WebGPURenderWindow.onInitialized(resolve);
250
+ model.WebGPURenderWindow.onInitialized(resolve);
251
251
  });
252
252
 
253
253
  case 8:
@@ -32,7 +32,8 @@ function vtkWebGPUMapperHelper(publicAPI, model) {
32
32
  sdrs.push(vDesc);
33
33
  sdrs.push(fDesc); // look for replacements to invoke
34
34
 
35
- var scode = model.vertexShaderTemplate + model.fragmentShaderTemplate;
35
+ var scode = model.vertexShaderTemplate + model.fragmentShaderTemplate; // eslint-disable-next-line prefer-regex-literals
36
+
36
37
  var re = new RegExp('//VTK::[^:]*::', 'g');
37
38
  var unique = scode.match(re).filter(function (v, i, a) {
38
39
  return a.indexOf(v) === i;
@@ -245,8 +245,8 @@ function vtkWebGPUPolyDataMapper(publicAPI, model) {
245
245
  case BufferUsage.Verts:
246
246
  return 'point-list';
247
247
 
248
- default:
249
248
  case BufferUsage.Lines:
249
+ default:
250
250
  return 'line-list';
251
251
  }
252
252
  };
@@ -45,9 +45,9 @@ function vtkWebGPUTextureManager(publicAPI, model) {
45
45
  req.format = 'rg';
46
46
  break;
47
47
 
48
- default:
49
48
  case 3:
50
49
  case 4:
50
+ default:
51
51
  req.format = 'rgba';
52
52
  break;
53
53
  }
@@ -8,7 +8,9 @@ import vtkWebGPUMapperHelper from './MapperHelper.js';
8
8
  import vtkWebGPURenderEncoder from './RenderEncoder.js';
9
9
  import vtkWebGPUShaderCache from './ShaderCache.js';
10
10
  import vtkWebGPUTexture from './Texture.js';
11
+ import vtkWebGPUFullScreenQuad from './FullScreenQuad.js';
11
12
  import vtkWebGPUVolumePassFSQ from './VolumePassFSQ.js';
13
+ import { f as distance2BetweenPoints } from '../../Common/Core/Math/index.js';
12
14
 
13
15
  var Representation = vtkProperty.Representation;
14
16
  var BufferUsage = vtkWebGPUBufferManager.BufferUsage,
@@ -31,6 +33,7 @@ var BufferUsage = vtkWebGPUBufferManager.BufferUsage,
31
33
 
32
34
  var cubeFaceTriangles = [[0, 4, 6], [0, 6, 2], [1, 3, 7], [1, 7, 5], [0, 5, 4], [0, 1, 5], [2, 6, 7], [2, 7, 3], [0, 3, 1], [0, 2, 3], [4, 5, 7], [4, 7, 6]];
33
35
  var DepthBoundsFS = "\n//VTK::Renderer::Dec\n\n//VTK::Select::Dec\n\n//VTK::VolumePass::Dec\n\n//VTK::TCoord::Dec\n\n//VTK::RenderEncoder::Dec\n\n//VTK::Mapper::Dec\n\n//VTK::IOStructs::Dec\n\n[[stage(fragment)]]\nfn main(\n//VTK::IOStructs::Input\n)\n//VTK::IOStructs::Output\n{\n var output : fragmentOutput;\n\n //VTK::Select::Impl\n\n //VTK::TCoord::Impl\n\n //VTK::VolumePass::Impl\n\n // use the maximum (closest) of the current value and the zbuffer\n // the blend func will then take the min to find the farthest stop value\n var stopval: f32 = max(input.fragPos.z, textureLoad(opaquePassDepthTexture, vec2<i32>(i32(input.fragPos.x), i32(input.fragPos.y)), 0));\n\n //VTK::RenderEncoder::Impl\n return output;\n}\n";
36
+ var volumeCopyFragTemplate = "\n//VTK::Renderer::Dec\n\n//VTK::Mapper::Dec\n\n//VTK::TCoord::Dec\n\n//VTK::RenderEncoder::Dec\n\n//VTK::IOStructs::Dec\n\n[[stage(fragment)]]\nfn main(\n//VTK::IOStructs::Input\n)\n//VTK::IOStructs::Output\n{\n var output: fragmentOutput;\n\n var computedColor: vec4<f32> = textureSample(volumePassSmallColorTexture,\n volumePassSmallColorTextureSampler, input.tcoordVS);\n\n //VTK::RenderEncoder::Impl\n return output;\n}\n";
34
37
  /* eslint-disable no-undef */
35
38
 
36
39
  /* eslint-disable no-bitwise */
@@ -38,7 +41,41 @@ var DepthBoundsFS = "\n//VTK::Renderer::Dec\n\n//VTK::Select::Dec\n\n//VTK::Volu
38
41
 
39
42
  function vtkWebGPUVolumePass(publicAPI, model) {
40
43
  // Set our className
41
- model.classHierarchy.push('vtkWebGPUVolumePass');
44
+ model.classHierarchy.push('vtkWebGPUVolumePass'); // create the required textures, encoders, FSQ etc
45
+
46
+ publicAPI.initialize = function (viewNode) {
47
+ if (!model._mergeEncoder) {
48
+ publicAPI.createMergeEncoder(viewNode);
49
+ }
50
+
51
+ if (!model._clearEncoder) {
52
+ publicAPI.createClearEncoder(viewNode);
53
+ }
54
+
55
+ if (!model._copyEncoder) {
56
+ publicAPI.createCopyEncoder(viewNode);
57
+ }
58
+
59
+ if (!model._depthRangeEncoder) {
60
+ publicAPI.createDepthRangeEncoder(viewNode);
61
+ }
62
+
63
+ if (!model.fullScreenQuad) {
64
+ model.fullScreenQuad = vtkWebGPUVolumePassFSQ.newInstance();
65
+ model.fullScreenQuad.setDevice(viewNode.getDevice());
66
+ model.fullScreenQuad.setTextureViews(_toConsumableArray(model._depthRangeEncoder.getColorTextureViews()));
67
+ }
68
+
69
+ if (!model._volumeCopyQuadQuad) {
70
+ model._volumeCopyQuad = vtkWebGPUFullScreenQuad.newInstance();
71
+
72
+ model._volumeCopyQuad.setPipelineHash('volpassfsq');
73
+
74
+ model._volumeCopyQuad.setDevice(viewNode.getDevice());
75
+
76
+ model._volumeCopyQuad.setFragmentShaderTemplate(volumeCopyFragTemplate);
77
+ }
78
+ };
42
79
 
43
80
  publicAPI.traverse = function (renNode, viewNode) {
44
81
  if (model.deleted) {
@@ -46,28 +83,159 @@ function vtkWebGPUVolumePass(publicAPI, model) {
46
83
  } // we just render our delegates in order
47
84
 
48
85
 
49
- model.currentParent = viewNode; // first render the boxes to generate a min max depth
86
+ model.currentParent = viewNode; // create stuff we need
87
+
88
+ publicAPI.initialize(viewNode); // determine if we are rendering a small size
89
+
90
+ publicAPI.computeTiming(viewNode); // first render the boxes to generate a min max depth
50
91
  // map for all the volumes
51
92
 
52
- publicAPI.renderDepthBounds(renNode, viewNode); // then perform the ray casting using the depth bounds texture
93
+ publicAPI.renderDepthBounds(renNode, viewNode); // always mark true
94
+
95
+ model._firstGroup = true;
96
+ var device = viewNode.getDevice(); // determine how many volumes we can render at a time. We subtract
97
+ // 4 because we use know we use textures for min, max, ofun and tfun
98
+
99
+ var maxVolumes = device.getHandle().limits.maxSampledTexturesPerShaderStage - 4; // if we have to make multiple passes then break the volumes up into groups
100
+ // rendered from farthest to closest
101
+
102
+ if (model.volumes.length > maxVolumes) {
103
+ var cameraPos = renNode.getRenderable().getActiveCamera().getPosition(); // sort from back to front based on volume centroid
104
+
105
+ var distances = [];
106
+
107
+ for (var v = 0; v < model.volumes.length; v++) {
108
+ var bounds = model.volumes[v].getRenderable().getBounds();
109
+ var centroid = [0.5 * (bounds[1] + bounds[0]), 0.5 * (bounds[3] + bounds[2]), 0.5 * (bounds[5] + bounds[4])];
110
+ distances[v] = distance2BetweenPoints(centroid, cameraPos);
111
+ } // sort by distance
112
+
113
+
114
+ var volumeOrder = _toConsumableArray(Array(model.volumes.length).keys());
115
+
116
+ volumeOrder.sort(function (a, b) {
117
+ return distances[b] - distances[a];
118
+ }); // render in chunks back to front
119
+
120
+ var volumesToRender = []; // start with smallest chunk so that the last (closest) chunk
121
+ // has a full maxVolumes;
122
+
123
+ var chunkSize = volumeOrder.length % maxVolumes;
124
+
125
+ for (var _v = 0; _v < volumeOrder.length; _v++) {
126
+ volumesToRender.push(model.volumes[volumeOrder[_v]]);
127
+
128
+ if (volumesToRender.length >= chunkSize) {
129
+ publicAPI.rayCastPass(viewNode, renNode, volumesToRender);
130
+ volumesToRender = [];
131
+ chunkSize = maxVolumes;
132
+ model._firstGroup = false;
133
+ }
134
+ }
135
+ } else {
136
+ // if not rendering in chunks then just draw all of them at once
137
+ publicAPI.rayCastPass(viewNode, renNode, model.volumes);
138
+ } // copy back to the original color buffer
139
+
140
+
141
+ if (model.small) {
142
+ model._volumeCopyQuad.setTextureViews([model._smallColorTextureView]);
143
+ } else {
144
+ model._volumeCopyQuad.setTextureViews([model._largeColorTextureView]);
145
+ } // final composite
146
+
147
+
148
+ model._copyEncoder.setColorTextureView(0, model.colorTextureView);
149
+
150
+ model._copyEncoder.attachTextureViews();
151
+
152
+ renNode.setRenderEncoder(model._copyEncoder);
153
+
154
+ model._copyEncoder.begin(viewNode.getCommandEncoder());
155
+
156
+ renNode.scissorAndViewport(model._copyEncoder);
157
+
158
+ model._volumeCopyQuad.setWebGPURenderer(renNode);
53
159
 
54
- if (!model.finalEncoder) {
55
- publicAPI.createFinalEncoder(viewNode);
160
+ model._volumeCopyQuad.render(model._copyEncoder, viewNode.getDevice());
161
+
162
+ model._copyEncoder.end();
163
+ }; // unsubscribe from our listeners
164
+
165
+
166
+ publicAPI.delete = macro.chain(function () {
167
+ if (model._animationRateSubscription) {
168
+ model._animationRateSubscription.unsubscribe();
169
+
170
+ model._animationRateSubscription = null;
171
+ }
172
+ }, publicAPI.delete);
173
+
174
+ publicAPI.computeTiming = function (viewNode) {
175
+ model.small = false;
176
+ var rwi = viewNode.getRenderable().getInteractor();
177
+
178
+ if (rwi.isAnimating() && model._lastScale > 1.5) {
179
+ model.small = true;
180
+ }
181
+
182
+ if (model.small) {
183
+ model._activeColorTextureView = model._smallColorTextureView;
184
+ } else {
185
+ model._largeColorTexture.resize(viewNode.getCanvas().width, viewNode.getCanvas().height);
186
+
187
+ model._activeColorTextureView = model._largeColorTextureView;
56
188
  }
57
189
 
58
- publicAPI.finalPass(viewNode, renNode);
190
+ if (!model._animationRateSubscription) {
191
+ // when the animation frame rate changes recompute the scale factor
192
+ model._animationRateSubscription = rwi.onAnimationFrameRateUpdate(function () {
193
+ var frate = rwi.getRecentAnimationFrameRate();
194
+ var targetScale = model._lastScale * rwi.getDesiredUpdateRate() / frate; // Do we need a resize? The values below are to provide some stickyness
195
+ // so that we are not changing texture size every second. Instead the targhet scale
196
+ // has to be a certain amount larger or smaller than the current value to force a
197
+ // change in texture size
198
+
199
+ if (targetScale > 1.4 * model._lastScale || targetScale < 0.7 * model._lastScale) {
200
+ model._lastScale = targetScale; // clamp scale to some reasonable values.
201
+ // Below 1.5 we will just be using full resolution as that is close enough
202
+ // Above 400 seems like a lot so we limit to that 1/20th per axis
203
+
204
+ if (model._lastScale > 400) {
205
+ model._lastScale = 400;
206
+ }
207
+
208
+ if (model._lastScale < 1.5) {
209
+ model._lastScale = 1.5;
210
+ } else {
211
+ var targetSmallWidth = 64 * Math.ceil(viewNode.getCanvas().width / (Math.sqrt(model._lastScale) * 64));
212
+ var targetSmallHeight = Math.ceil(targetSmallWidth * viewNode.getCanvas().height / viewNode.getCanvas().width);
213
+
214
+ model._smallColorTexture.resize(targetSmallWidth, targetSmallHeight);
215
+ }
216
+ }
217
+ });
218
+ }
59
219
  };
60
220
 
61
- publicAPI.finalPass = function (viewNode, renNode) {
62
- model.finalEncoder.setColorTextureView(0, model.colorTextureView);
63
- model.finalEncoder.attachTextureViews();
64
- renNode.setRenderEncoder(model.finalEncoder);
65
- model.finalEncoder.begin(viewNode.getCommandEncoder());
66
- renNode.scissorAndViewport(model.finalEncoder);
221
+ publicAPI.rayCastPass = function (viewNode, renNode, volumes) {
222
+ var encoder = model._firstGroup ? model._clearEncoder : model._mergeEncoder;
223
+ encoder.setColorTextureView(0, model._activeColorTextureView);
224
+ encoder.attachTextureViews();
225
+ renNode.setRenderEncoder(encoder);
226
+ encoder.begin(viewNode.getCommandEncoder());
227
+
228
+ var width = model._activeColorTextureView.getTexture().getWidth();
229
+
230
+ var height = model._activeColorTextureView.getTexture().getHeight();
231
+
232
+ encoder.getHandle().setViewport(0, 0, width, height, 0.0, 1.0); // set scissor
233
+
234
+ encoder.getHandle().setScissorRect(0, 0, width, height);
67
235
  model.fullScreenQuad.setWebGPURenderer(renNode);
68
- model.fullScreenQuad.setVolumes(model.volumes);
69
- model.fullScreenQuad.render(model.finalEncoder, viewNode.getDevice());
70
- model.finalEncoder.end();
236
+ model.fullScreenQuad.setVolumes(volumes);
237
+ model.fullScreenQuad.render(encoder, viewNode.getDevice());
238
+ encoder.end();
71
239
  };
72
240
 
73
241
  publicAPI.renderDepthBounds = function (renNode, viewNode) {
@@ -114,7 +282,7 @@ function vtkWebGPUVolumePass(publicAPI, model) {
114
282
 
115
283
  var stime = renNode.getStabilizedTime();
116
284
 
117
- if (!model._lastMTimes[model.volumes.length] || stime !== model._lastMTimes[model.volumes.length]) {
285
+ if (model._lastMTimes.length <= model.volumes.length || stime !== model._lastMTimes[model.volumes.length]) {
118
286
  update = true;
119
287
  model._lastMTimes[model.volumes.length] = stime;
120
288
  } // if no need to update then return
@@ -165,55 +333,32 @@ function vtkWebGPUVolumePass(publicAPI, model) {
165
333
  publicAPI.drawDepthRange = function (renNode, viewNode) {
166
334
  var device = viewNode.getDevice(); // copy current depth buffer to
167
335
 
168
- if (!model.depthRangeEncoder) {
169
- publicAPI.createDepthRangeEncoder();
170
- model.depthRangeTexture = vtkWebGPUTexture.newInstance();
171
- model.depthRangeTexture.create(device, {
172
- width: viewNode.getCanvas().width,
173
- height: viewNode.getCanvas().height,
174
- format: 'r16float',
175
- usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
176
- });
177
- var maxView = model.depthRangeTexture.createView();
178
- maxView.setName('maxTexture');
179
- model.depthRangeEncoder.setColorTextureView(0, maxView);
180
- model.depthRangeTexture2 = vtkWebGPUTexture.newInstance();
181
- model.depthRangeTexture2.create(device, {
182
- width: viewNode.getCanvas().width,
183
- height: viewNode.getCanvas().height,
184
- format: 'r16float',
185
- usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
186
- });
187
- var minView = model.depthRangeTexture2.createView();
188
- minView.setName('minTexture');
189
- model.depthRangeEncoder.setColorTextureView(1, minView);
336
+ model._depthRangeTexture.resizeToMatch(model.colorTextureView.getTexture());
190
337
 
191
- model._mapper.setDevice(viewNode.getDevice());
338
+ model._depthRangeTexture2.resizeToMatch(model.colorTextureView.getTexture());
192
339
 
193
- model._mapper.setTextureViews([model.depthTextureView]);
194
- } else {
195
- model.depthRangeTexture.resizeToMatch(model.colorTextureView.getTexture());
196
- model.depthRangeTexture2.resizeToMatch(model.colorTextureView.getTexture());
197
- }
340
+ model._depthRangeEncoder.attachTextureViews();
198
341
 
199
- model.depthRangeEncoder.attachTextureViews();
200
342
  publicAPI.setCurrentOperation('volumeDepthRangePass');
201
- renNode.setRenderEncoder(model.depthRangeEncoder);
343
+ renNode.setRenderEncoder(model._depthRangeEncoder);
202
344
  renNode.volumeDepthRangePass(true);
203
345
 
204
346
  model._mapper.setWebGPURenderer(renNode);
205
347
 
206
- model._mapper.build(model.depthRangeEncoder, device);
348
+ model._mapper.build(model._depthRangeEncoder, device);
207
349
 
208
350
  model._mapper.registerToDraw();
209
351
 
210
352
  renNode.volumeDepthRangePass(false);
211
353
  };
212
354
 
213
- publicAPI.createDepthRangeEncoder = function () {
214
- model.depthRangeEncoder = vtkWebGPURenderEncoder.newInstance();
215
- model.depthRangeEncoder.setPipelineHash('volr');
216
- model.depthRangeEncoder.setReplaceShaderCodeFunction(function (pipeline) {
355
+ publicAPI.createDepthRangeEncoder = function (viewNode) {
356
+ var device = viewNode.getDevice();
357
+ model._depthRangeEncoder = vtkWebGPURenderEncoder.newInstance();
358
+
359
+ model._depthRangeEncoder.setPipelineHash('volr');
360
+
361
+ model._depthRangeEncoder.setReplaceShaderCodeFunction(function (pipeline) {
217
362
  var fDesc = pipeline.getShaderDescription('fragment');
218
363
  fDesc.addOutput('vec4<f32>', 'outColor1');
219
364
  fDesc.addOutput('vec4<f32>', 'outColor2');
@@ -221,7 +366,8 @@ function vtkWebGPUVolumePass(publicAPI, model) {
221
366
  code = vtkWebGPUShaderCache.substitute(code, '//VTK::RenderEncoder::Impl', ['output.outColor1 = vec4<f32>(input.fragPos.z, 0.0, 0.0, 0.0);', 'output.outColor2 = vec4<f32>(stopval, 0.0, 0.0, 0.0);']).result;
222
367
  fDesc.setCode(code);
223
368
  });
224
- model.depthRangeEncoder.setDescription({
369
+
370
+ model._depthRangeEncoder.setDescription({
225
371
  colorAttachments: [{
226
372
  view: null,
227
373
  loadValue: [0.0, 0.0, 0.0, 0.0],
@@ -232,7 +378,8 @@ function vtkWebGPUVolumePass(publicAPI, model) {
232
378
  storeOp: 'store'
233
379
  }]
234
380
  });
235
- model.depthRangeEncoder.setPipelineSettings({
381
+
382
+ model._depthRangeEncoder.setPipelineSettings({
236
383
  primitive: {
237
384
  cullMode: 'none'
238
385
  },
@@ -267,30 +414,184 @@ function vtkWebGPUVolumePass(publicAPI, model) {
267
414
  }
268
415
  }]
269
416
  }
417
+ }); // and the textures it needs
418
+
419
+
420
+ model._depthRangeTexture = vtkWebGPUTexture.newInstance();
421
+
422
+ model._depthRangeTexture.create(device, {
423
+ width: viewNode.getCanvas().width,
424
+ height: viewNode.getCanvas().height,
425
+ format: 'r16float',
426
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
427
+ });
428
+
429
+ var maxView = model._depthRangeTexture.createView();
430
+
431
+ maxView.setName('maxTexture');
432
+
433
+ model._depthRangeEncoder.setColorTextureView(0, maxView);
434
+
435
+ model._depthRangeTexture2 = vtkWebGPUTexture.newInstance();
436
+
437
+ model._depthRangeTexture2.create(device, {
438
+ width: viewNode.getCanvas().width,
439
+ height: viewNode.getCanvas().height,
440
+ format: 'r16float',
441
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
442
+ });
443
+
444
+ var minView = model._depthRangeTexture2.createView();
445
+
446
+ minView.setName('minTexture');
447
+
448
+ model._depthRangeEncoder.setColorTextureView(1, minView);
449
+
450
+ model._mapper.setDevice(viewNode.getDevice());
451
+
452
+ model._mapper.setTextureViews([model.depthTextureView]);
453
+ };
454
+
455
+ publicAPI.createClearEncoder = function (viewNode) {
456
+ model._smallColorTexture = vtkWebGPUTexture.newInstance(); // multiple of 64 pixels to help with texture alignment/size issues
457
+ // as webgpu textures have to be multiples of 256 bytes wide
458
+ // for data transfers (just in case)
459
+
460
+ var targetSmallWidth = 64 * Math.ceil(0.7 * viewNode.getCanvas().width / 64);
461
+
462
+ model._smallColorTexture.create(viewNode.getDevice(), {
463
+ width: targetSmallWidth,
464
+ height: Math.ceil(targetSmallWidth * viewNode.getCanvas().height / viewNode.getCanvas().width),
465
+ format: 'bgra8unorm',
466
+
467
+ /* eslint-disable no-undef */
468
+
469
+ /* eslint-disable no-bitwise */
470
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC
471
+ });
472
+
473
+ model._smallColorTextureView = model._smallColorTexture.createView();
474
+
475
+ model._smallColorTextureView.setName('volumePassSmallColorTexture');
476
+
477
+ model._smallColorTextureView.addSampler(viewNode.getDevice(), {
478
+ minFilter: 'linear',
479
+ magFilter: 'linear'
480
+ });
481
+
482
+ model._largeColorTexture = vtkWebGPUTexture.newInstance();
483
+
484
+ model._largeColorTexture.create(viewNode.getDevice(), {
485
+ width: viewNode.getCanvas().width,
486
+ height: viewNode.getCanvas().height,
487
+ format: 'bgra8unorm',
488
+
489
+ /* eslint-disable no-undef */
490
+
491
+ /* eslint-disable no-bitwise */
492
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC
493
+ });
494
+
495
+ model._largeColorTextureView = model._largeColorTexture.createView();
496
+
497
+ model._largeColorTextureView.setName('volumePassSmallColorTexture');
498
+
499
+ model._largeColorTextureView.addSampler(viewNode.getDevice(), {
500
+ minFilter: 'linear',
501
+ magFilter: 'linear'
502
+ });
503
+
504
+ model._clearEncoder = vtkWebGPURenderEncoder.newInstance();
505
+
506
+ model._clearEncoder.setDescription({
507
+ colorAttachments: [{
508
+ view: null,
509
+ loadValue: [0.0, 0.0, 0.0, 0.0],
510
+ storeOp: 'store'
511
+ }]
512
+ });
513
+
514
+ model._clearEncoder.setPipelineHash('volpf');
515
+
516
+ model._clearEncoder.setPipelineSettings({
517
+ primitive: {
518
+ cullMode: 'none'
519
+ },
520
+ fragment: {
521
+ targets: [{
522
+ format: 'bgra8unorm',
523
+ blend: {
524
+ color: {
525
+ srcFactor: 'src-alpha',
526
+ dstFactor: 'one-minus-src-alpha'
527
+ },
528
+ alpha: {
529
+ srcfactor: 'one',
530
+ dstFactor: 'one-minus-src-alpha'
531
+ }
532
+ }
533
+ }]
534
+ }
535
+ });
536
+ };
537
+
538
+ publicAPI.createCopyEncoder = function (viewNode) {
539
+ model._copyEncoder = vtkWebGPURenderEncoder.newInstance();
540
+
541
+ model._copyEncoder.setDescription({
542
+ colorAttachments: [{
543
+ view: null,
544
+ loadValue: 'load',
545
+ storeOp: 'store'
546
+ }]
547
+ });
548
+
549
+ model._copyEncoder.setPipelineHash('volcopypf');
550
+
551
+ model._copyEncoder.setPipelineSettings({
552
+ primitive: {
553
+ cullMode: 'none'
554
+ },
555
+ fragment: {
556
+ targets: [{
557
+ format: 'bgra8unorm',
558
+ blend: {
559
+ color: {
560
+ srcFactor: 'one',
561
+ dstFactor: 'one-minus-src-alpha'
562
+ },
563
+ alpha: {
564
+ srcfactor: 'one',
565
+ dstFactor: 'one-minus-src-alpha'
566
+ }
567
+ }
568
+ }]
569
+ }
270
570
  });
271
571
  };
272
572
 
273
- publicAPI.createFinalEncoder = function (viewNode) {
274
- model.fullScreenQuad = vtkWebGPUVolumePassFSQ.newInstance();
275
- model.fullScreenQuad.setDevice(viewNode.getDevice());
276
- model.fullScreenQuad.setTextureViews(_toConsumableArray(model.depthRangeEncoder.getColorTextureViews()));
277
- model.finalEncoder = vtkWebGPURenderEncoder.newInstance();
278
- model.finalEncoder.setDescription({
573
+ publicAPI.createMergeEncoder = function (viewNode) {
574
+ model._mergeEncoder = vtkWebGPURenderEncoder.newInstance();
575
+
576
+ model._mergeEncoder.setDescription({
279
577
  colorAttachments: [{
280
578
  view: null,
281
579
  loadValue: 'load',
282
580
  storeOp: 'store'
283
581
  }]
284
582
  });
285
- model.finalEncoder.setReplaceShaderCodeFunction(function (pipeline) {
583
+
584
+ model._mergeEncoder.setReplaceShaderCodeFunction(function (pipeline) {
286
585
  var fDesc = pipeline.getShaderDescription('fragment');
287
586
  fDesc.addOutput('vec4<f32>', 'outColor');
288
587
  var code = fDesc.getCode();
289
- code = vtkWebGPUShaderCache.substitute(code, '//VTK::RenderEncoder::Impl', ['output.outColor = vec4<f32>(computedColor.rgb*computedColor.a, computedColor.a);']).result;
588
+ code = vtkWebGPUShaderCache.substitute(code, '//VTK::RenderEncoder::Impl', ['output.outColor = vec4<f32>(computedColor.rgb, computedColor.a);']).result;
290
589
  fDesc.setCode(code);
291
590
  });
292
- model.finalEncoder.setPipelineHash('volpf');
293
- model.finalEncoder.setPipelineSettings({
591
+
592
+ model._mergeEncoder.setPipelineHash('volpf');
593
+
594
+ model._mergeEncoder.setPipelineSettings({
294
595
  primitive: {
295
596
  cullMode: 'none'
296
597
  },
@@ -299,7 +600,7 @@ function vtkWebGPUVolumePass(publicAPI, model) {
299
600
  format: 'bgra8unorm',
300
601
  blend: {
301
602
  color: {
302
- srcFactor: 'one',
603
+ srcFactor: 'src-alpha',
303
604
  dstFactor: 'one-minus-src-alpha'
304
605
  },
305
606
  alpha: {
@@ -344,6 +645,7 @@ function extend(publicAPI, model) {
344
645
  Object.assign(model, DEFAULT_VALUES, initialValues); // Build VTK API
345
646
 
346
647
  vtkRenderPass.extend(publicAPI, model, initialValues);
648
+ model._lastScale = 2.0;
347
649
  model._mapper = vtkWebGPUMapperHelper.newInstance();
348
650
 
349
651
  model._mapper.setFragmentShaderTemplate(DepthBoundsFS);