@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.
- package/Common/Core/CellArray.js +2 -2
- package/Common/Core/DataArray.js +2 -2
- package/Common/Core/MatrixBuilder.d.ts +1 -1
- package/Common/Core/ScalarsToColors.js +12 -11
- package/Common/DataModel/BoundingBox.js +2 -2
- package/Common/DataModel/Box.js +2 -2
- package/Common/DataModel/CellTypes.js +2 -2
- package/Common/DataModel/Cylinder.js +2 -2
- package/Common/DataModel/DataSet.js +2 -2
- package/Common/DataModel/DataSetAttributes.js +2 -2
- package/Common/DataModel/ImplicitBoolean.js +2 -2
- package/Common/DataModel/Line.js +2 -2
- package/Common/DataModel/PiecewiseFunction.js +3 -3
- package/Common/DataModel/Plane.js +2 -2
- package/Common/DataModel/SelectionNode.js +2 -2
- package/Common/DataModel/Sphere.js +2 -2
- package/Common/DataModel/StructuredData.js +2 -2
- package/Common/DataModel/Triangle.js +2 -2
- package/Common/Transform/LandmarkTransform.js +2 -2
- package/Filters/Core/Cutter.js +2 -2
- package/Filters/General/Calculator.js +2 -2
- package/Filters/Sources/Arrow2DSource.js +2 -2
- package/Filters/Sources/CircleSource.js +2 -2
- package/IO/Core/DataAccessHelper/HtmlDataAccessHelper.js +6 -12
- package/IO/Core/DataAccessHelper/HttpDataAccessHelper.js +11 -19
- package/IO/Core/DataAccessHelper/JSZipDataAccessHelper.js +8 -15
- package/IO/Core/DataAccessHelper/LiteHttpDataAccessHelper.js +11 -19
- package/IO/Core/HttpSceneLoader.js +2 -2
- package/IO/Core/ImageStream/DefaultProtocol.js +2 -6
- package/IO/Geometry/PLYWriter/Constants.js +19 -0
- package/IO/Geometry/PLYWriter.d.ts +203 -0
- package/IO/Geometry/PLYWriter.js +323 -0
- package/IO/Geometry/STLWriter.js +2 -2
- package/IO/Geometry.js +3 -1
- package/IO/XML/XMLImageDataWriter.js +2 -2
- package/IO/XML/XMLPolyDataWriter.js +2 -2
- package/Imaging/Core/AbstractImageInterpolator/InterpolationInfo.js +2 -2
- package/Imaging/Core/AbstractImageInterpolator.js +2 -2
- package/Imaging/Core/ImageInterpolator.js +12 -12
- package/Imaging/Core/ImageReslice.js +10 -10
- package/Imaging/Hybrid/SampleFunction.js +2 -2
- package/Interaction/Animations/TimeStepBasedAnimationHandler.js +2 -2
- package/Interaction/Manipulators/MouseBoxSelectorManipulator.js +2 -2
- package/Interaction/Style/InteractorStyleManipulator.js +2 -2
- package/Interaction/Style/InteractorStyleRemoteMouse.js +2 -2
- package/Interaction/UI/FPSMonitor.js +2 -2
- package/Interaction/UI/Slider.js +2 -2
- package/Interaction/Widgets/AbstractWidget.js +2 -2
- package/Interaction/Widgets/DistanceRepresentation.js +2 -2
- package/Interaction/Widgets/DistanceWidget.js +2 -2
- package/Interaction/Widgets/HandleRepresentation.js +2 -2
- package/Interaction/Widgets/HandleWidget.js +2 -2
- package/Interaction/Widgets/ImageCroppingRegionsWidget.js +2 -2
- package/Interaction/Widgets/LabelRepresentation.js +2 -2
- package/Interaction/Widgets/LabelWidget.js +2 -2
- package/Interaction/Widgets/LineRepresentation.js +2 -2
- package/Interaction/Widgets/LineWidget.js +2 -2
- package/Interaction/Widgets/OrientationMarkerWidget.js +2 -2
- package/Interaction/Widgets/PiecewiseGaussianWidget.js +2 -2
- package/Interaction/Widgets/ResliceCursor/ResliceCursor.js +2 -2
- package/Interaction/Widgets/ResliceCursor/ResliceCursorActor.js +2 -2
- package/Interaction/Widgets/ResliceCursor/ResliceCursorPolyDataAlgorithm.js +2 -2
- package/Interaction/Widgets/ResliceCursor/ResliceCursorWidget.js +2 -2
- package/Interaction/Widgets/SphereHandleRepresentation.js +2 -2
- package/Proxy/Core/PiecewiseFunctionProxy.js +2 -2
- package/Proxy/Core/ProxyManager/core.js +2 -2
- package/Proxy/Core/ProxyManager/properties.js +2 -2
- package/Proxy/Core/ProxyManager/state.js +2 -2
- package/Proxy/Representations/SliceRepresentationProxy.js +2 -2
- package/Rendering/Core/AbstractMapper.d.ts +4 -4
- package/Rendering/Core/AbstractMapper.js +18 -7
- package/Rendering/Core/Actor.js +2 -2
- package/Rendering/Core/AnnotatedCubeActor.js +2 -2
- package/Rendering/Core/AxesActor.js +2 -2
- package/Rendering/Core/CellPicker.js +2 -2
- package/Rendering/Core/ColorTransferFunction.js +2 -2
- package/Rendering/Core/Coordinate.js +2 -2
- package/Rendering/Core/CubeAxesActor.js +2 -2
- package/Rendering/Core/Follower.js +2 -2
- package/Rendering/Core/Glyph3DMapper.js +2 -2
- package/Rendering/Core/ImageMapper.js +2 -2
- package/Rendering/Core/InteractorObserver.js +2 -2
- package/Rendering/Core/InteractorStyle.js +2 -2
- package/Rendering/Core/Mapper.js +2 -2
- package/Rendering/Core/Picker.js +2 -2
- package/Rendering/Core/Property.js +2 -2
- package/Rendering/Core/RenderWindowInteractor.js +36 -14
- package/Rendering/Core/ScalarBarActor.js +2 -2
- package/Rendering/Core/VolumeMapper.js +1 -4
- package/Rendering/Core/VolumeProperty.js +2 -2
- package/Rendering/Core.js +2 -2
- package/Rendering/Misc/RenderWindowWithControlBar.js +2 -2
- package/Rendering/Misc/SynchronizableRenderWindow/vtkObjectManager.js +2 -2
- package/Rendering/Misc/SynchronizableRenderWindow.js +2 -2
- package/Rendering/OpenGL/BufferObject.js +5 -5
- package/Rendering/OpenGL/CellArrayBufferObject.js +2 -1
- package/Rendering/OpenGL/Glyph3DMapper.js +2 -2
- package/Rendering/OpenGL/HardwareSelector.js +2 -2
- package/Rendering/OpenGL/RenderWindow.js +1 -1
- package/Rendering/OpenGL/SphereMapper.js +2 -2
- package/Rendering/OpenGL/StickMapper.js +2 -2
- package/Rendering/OpenGL/SurfaceLIC/SurfaceLICMapper.js +2 -2
- package/Rendering/OpenGL/Texture.js +2 -2
- package/Rendering/OpenGL/VolumeMapper.js +11 -18
- package/Rendering/WebGPU/Buffer.js +2 -2
- package/Rendering/WebGPU/BufferManager.js +2 -2
- package/Rendering/WebGPU/Glyph3DMapper.js +2 -2
- package/Rendering/WebGPU/HardwareSelector.js +1 -1
- package/Rendering/WebGPU/MapperHelper.js +2 -1
- package/Rendering/WebGPU/PolyDataMapper.js +1 -1
- package/Rendering/WebGPU/TextureManager.js +1 -1
- package/Rendering/WebGPU/VolumePass.js +366 -64
- package/Rendering/WebGPU/VolumePassFSQ.js +5 -2
- package/Widgets/Core/AbstractWidgetFactory.js +2 -2
- package/Widgets/Representations/ArrowHandleRepresentation.js +2 -2
- package/Widgets/Representations/ContextRepresentation.js +2 -2
- package/Widgets/Representations/HandleRepresentation.js +2 -2
- package/Widgets/Representations/PolyLineRepresentation.js +2 -2
- package/Widgets/Representations/ResliceCursorContextRepresentation.js +2 -2
- package/Widgets/SVG/SVGLandmarkRepresentation.js +2 -2
- package/Widgets/Widgets3D/EllipseWidget/behavior.js +2 -2
- package/Widgets/Widgets3D/EllipseWidget.js +2 -2
- package/Widgets/Widgets3D/InteractiveOrientationWidget/behavior.js +2 -2
- package/Widgets/Widgets3D/LineWidget/behavior.js +2 -2
- package/Widgets/Widgets3D/RectangleWidget/behavior.js +2 -2
- package/Widgets/Widgets3D/RectangleWidget.js +2 -2
- package/Widgets/Widgets3D/ShapeWidget/behavior.js +2 -2
- package/Widgets/Widgets3D/ShapeWidget.js +2 -2
- package/_virtual/rollup-plugin-worker-loader__module_Sources/Filters/General/PaintFilter/PaintFilter.worker.js +44 -44
- package/_virtual/rollup-plugin-worker-loader__module_Sources/Interaction/Widgets/PiecewiseGaussianWidget/ComputeHistogram.worker.js +1 -1
- package/macros.js +16 -32
- package/package.json +52 -54
- package/vtk.js +2 -2
- 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);
|
|
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]
|
|
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);
|
|
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]
|
|
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
|
-
|
|
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;
|
|
@@ -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; //
|
|
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); //
|
|
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
|
-
|
|
55
|
-
|
|
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
|
-
|
|
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.
|
|
62
|
-
model.
|
|
63
|
-
model.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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(
|
|
69
|
-
model.fullScreenQuad.render(
|
|
70
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
338
|
+
model._depthRangeTexture2.resizeToMatch(model.colorTextureView.getTexture());
|
|
192
339
|
|
|
193
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
215
|
-
model.
|
|
216
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
274
|
-
model.
|
|
275
|
-
|
|
276
|
-
model.
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
293
|
-
model.
|
|
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: '
|
|
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);
|