@kitware/vtk.js 28.4.0 → 28.5.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/Rendering/Core/VolumeMapper.d.ts +27 -0
- package/Rendering/Core/VolumeMapper.js +3 -1
- package/Rendering/OpenGL/RenderWindow.d.ts +0 -18
- package/Rendering/OpenGL/RenderWindow.js +3 -11
- package/Rendering/OpenGL/VolumeMapper.js +27 -13
- package/Rendering/WebGPU/VolumePass.js +11 -10
- package/package.json +1 -1
|
@@ -68,6 +68,21 @@ export interface vtkVolumeMapper extends vtkAbstractMapper {
|
|
|
68
68
|
*/
|
|
69
69
|
getAutoAdjustSampleDistances(): boolean;
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Get at what scale the quality is reduced when interacting for the first time with the volume
|
|
73
|
+
* It should should be set before any call to render for this volume
|
|
74
|
+
* The higher the scale is, the lower the quality of rendering is during interaction
|
|
75
|
+
* @default 16
|
|
76
|
+
*/
|
|
77
|
+
getInitialInteractionScale(): number;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Get by how much the sample distance should be increased when interacting
|
|
81
|
+
* This feature is only implemented in the OpenGL volume mapper
|
|
82
|
+
* @default 4
|
|
83
|
+
*/
|
|
84
|
+
getInteractionSampleDistanceFactor(): number;
|
|
85
|
+
|
|
71
86
|
/**
|
|
72
87
|
*
|
|
73
88
|
*/
|
|
@@ -188,6 +203,18 @@ export interface vtkVolumeMapper extends vtkAbstractMapper {
|
|
|
188
203
|
*/
|
|
189
204
|
setAutoAdjustSampleDistances(autoAdjustSampleDistances: boolean): boolean;
|
|
190
205
|
|
|
206
|
+
/**
|
|
207
|
+
*
|
|
208
|
+
* @param initialInteractionScale
|
|
209
|
+
*/
|
|
210
|
+
setInitialInteractionScale(initialInteractionScale: number): boolean;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
*
|
|
214
|
+
* @param interactionSampleDistanceFactor
|
|
215
|
+
*/
|
|
216
|
+
setInteractionSampleDistanceFactor(interactionSampleDistanceFactor: number): boolean;
|
|
217
|
+
|
|
191
218
|
/**
|
|
192
219
|
* Set the normal computation to be dependent on the transfer function.
|
|
193
220
|
* By default, the mapper relies on the scalar gradient for computing normals at sample locations
|
|
@@ -147,6 +147,8 @@ var DEFAULT_VALUES = {
|
|
|
147
147
|
imageSampleDistance: 1.0,
|
|
148
148
|
maximumSamplesPerRay: 1000,
|
|
149
149
|
autoAdjustSampleDistances: true,
|
|
150
|
+
initialInteractionScale: 1.0,
|
|
151
|
+
interactionSampleDistanceFactor: 1.0,
|
|
150
152
|
blendMode: BlendMode.COMPOSITE_BLEND,
|
|
151
153
|
ipScalarRange: [-1000000.0, 1000000.0],
|
|
152
154
|
filterMode: FilterMode.OFF,
|
|
@@ -169,7 +171,7 @@ function extend(publicAPI, model) {
|
|
|
169
171
|
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
170
172
|
Object.assign(model, DEFAULT_VALUES, initialValues);
|
|
171
173
|
vtkAbstractMapper.extend(publicAPI, model, initialValues);
|
|
172
|
-
macro.setGet(publicAPI, model, ['sampleDistance', 'imageSampleDistance', 'maximumSamplesPerRay', 'autoAdjustSampleDistances', 'blendMode', 'filterMode', 'preferSizeOverAccuracy', 'computeNormalFromOpacity', 'volumetricScatteringBlending', 'globalIlluminationReach', 'volumeShadowSamplingDistFactor', 'anisotropy', 'localAmbientOcclusion', 'LAOKernelSize', 'LAOKernelRadius']);
|
|
174
|
+
macro.setGet(publicAPI, model, ['sampleDistance', 'imageSampleDistance', 'maximumSamplesPerRay', 'autoAdjustSampleDistances', 'initialInteractionScale', 'interactionSampleDistanceFactor', 'blendMode', 'filterMode', 'preferSizeOverAccuracy', 'computeNormalFromOpacity', 'volumetricScatteringBlending', 'globalIlluminationReach', 'volumeShadowSamplingDistFactor', 'anisotropy', 'localAmbientOcclusion', 'LAOKernelSize', 'LAOKernelRadius']);
|
|
173
175
|
macro.setGetArray(publicAPI, model, ['ipScalarRange'], 2);
|
|
174
176
|
macro.event(publicAPI, model, 'lightingActivated'); // Object methods
|
|
175
177
|
|
|
@@ -377,24 +377,6 @@ export interface vtkOpenGLRenderWindow extends vtkOpenGLRenderWindowBase {
|
|
|
377
377
|
*/
|
|
378
378
|
getSize(): Vector2;
|
|
379
379
|
|
|
380
|
-
/**
|
|
381
|
-
*
|
|
382
|
-
* @param {Vector2} size
|
|
383
|
-
*/
|
|
384
|
-
setVrResolution(size: Vector2): void;
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
*
|
|
388
|
-
* @param {Number} x
|
|
389
|
-
* @param {Number} y
|
|
390
|
-
*/
|
|
391
|
-
setVrResolution(x: number, y: number): void;
|
|
392
|
-
|
|
393
|
-
/**
|
|
394
|
-
*
|
|
395
|
-
*/
|
|
396
|
-
getVrResolution(): Vector2;
|
|
397
|
-
|
|
398
380
|
/**
|
|
399
381
|
* Scales the size of a browser CSS pixel to a rendered canvas pixel.
|
|
400
382
|
* `const renderedPixelWidth = cssPixelWidth * apiRenderWindow.getComputedDevicePixelRatio()`
|
|
@@ -93,9 +93,7 @@ function vtkOpenGLRenderWindow(publicAPI, model) {
|
|
|
93
93
|
|
|
94
94
|
|
|
95
95
|
model.canvas.addEventListener('webglcontextlost', _preventDefault, false);
|
|
96
|
-
model.canvas.addEventListener('webglcontextrestored', publicAPI.restoreContext, false); //
|
|
97
|
-
|
|
98
|
-
var isImmersiveVrSupported = navigator.xr !== undefined && navigator.xr.isSessionSupported('immersive-vr'); // Auto update style
|
|
96
|
+
model.canvas.addEventListener('webglcontextrestored', publicAPI.restoreContext, false); // Auto update style
|
|
99
97
|
|
|
100
98
|
var previousSize = [0, 0];
|
|
101
99
|
|
|
@@ -233,12 +231,7 @@ function vtkOpenGLRenderWindow(publicAPI, model) {
|
|
|
233
231
|
alpha: true,
|
|
234
232
|
powerPreference: 'high-performance'
|
|
235
233
|
};
|
|
236
|
-
var result = null;
|
|
237
|
-
|
|
238
|
-
if (isImmersiveVrSupported) {
|
|
239
|
-
publicAPI.invokeHaveVRDisplay();
|
|
240
|
-
}
|
|
241
|
-
|
|
234
|
+
var result = null;
|
|
242
235
|
var webgl2Supported = typeof WebGL2RenderingContext !== 'undefined';
|
|
243
236
|
model.webgl2 = false;
|
|
244
237
|
|
|
@@ -988,8 +981,7 @@ function extend(publicAPI, model) {
|
|
|
988
981
|
model.shaderCache.setOpenGLRenderWindow(publicAPI); // setup default forward pass rendering
|
|
989
982
|
|
|
990
983
|
model.renderPasses[0] = vtkForwardPass.newInstance();
|
|
991
|
-
macro.event(publicAPI, model, 'imageReady');
|
|
992
|
-
macro.event(publicAPI, model, 'haveVRDisplay'); // Build VTK API
|
|
984
|
+
macro.event(publicAPI, model, 'imageReady'); // Build VTK API
|
|
993
985
|
|
|
994
986
|
macro.get(publicAPI, model, ['shaderCache', 'textureUnitManager', 'webgl2', 'vrDisplay', 'useBackgroundImage', 'xrSupported', 'activeFramebuffer']);
|
|
995
987
|
macro.setGet(publicAPI, model, ['initialized', 'context', 'canvas', 'renderPasses', 'notifyStartCaptureImage', 'defaultToWebgl2', 'cursor', 'useOffScreen']);
|
|
@@ -145,7 +145,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
145
145
|
var spc = model.currentInput.getSpacing();
|
|
146
146
|
var vsize = new Float64Array(3);
|
|
147
147
|
vec3.set(vsize, (ext[1] - ext[0]) * spc[0], (ext[3] - ext[2]) * spc[1], (ext[5] - ext[4]) * spc[2]);
|
|
148
|
-
var maxSamples = vec3.length(vsize) /
|
|
148
|
+
var maxSamples = vec3.length(vsize) / publicAPI.getCurrentSampleDistance(ren);
|
|
149
149
|
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::MaximumSamplesValue', "".concat(Math.ceil(maxSamples))).result; // set light complexity
|
|
150
150
|
|
|
151
151
|
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::LightComplexity', "#define vtkLightComplexity ".concat(model.lastLightComplexity)).result; // set shadow blending flag
|
|
@@ -297,7 +297,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
297
297
|
var spc = model.currentInput.getSpacing();
|
|
298
298
|
var vsize = new Float64Array(3);
|
|
299
299
|
vec3.set(vsize, (ext[1] - ext[0]) * spc[0], (ext[3] - ext[2]) * spc[1], (ext[5] - ext[4]) * spc[2]);
|
|
300
|
-
var maxSamples = vec3.length(vsize) /
|
|
300
|
+
var maxSamples = vec3.length(vsize) / publicAPI.getCurrentSampleDistance(ren);
|
|
301
301
|
var state = {
|
|
302
302
|
interpolationType: actor.getProperty().getInterpolationType(),
|
|
303
303
|
useLabelOutline: actor.getProperty().getUseLabelOutline(),
|
|
@@ -372,7 +372,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
program.setUniformi('texture1', model.scalarTexture.getTextureUnit());
|
|
375
|
-
program.setUniformf('sampleDistance',
|
|
375
|
+
program.setUniformf('sampleDistance', publicAPI.getCurrentSampleDistance(ren));
|
|
376
376
|
var volInfo = model.scalarTexture.getVolumeInfo();
|
|
377
377
|
var ipScalarRange = model.renderable.getIpScalarRange();
|
|
378
378
|
var minVals = [];
|
|
@@ -467,7 +467,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
467
467
|
mat4.multiply(model.idxToView, model.modelToView, i2wmat4);
|
|
468
468
|
mat3.multiply(model.idxNormalMatrix, keyMats.normalMatrix, actMats.normalMatrix);
|
|
469
469
|
mat3.multiply(model.idxNormalMatrix, model.idxNormalMatrix, model.currentInput.getDirectionByReference());
|
|
470
|
-
var maxSamples = vec3.length(vsize) /
|
|
470
|
+
var maxSamples = vec3.length(vsize) / publicAPI.getCurrentSampleDistance(ren);
|
|
471
471
|
|
|
472
472
|
if (maxSamples > model.renderable.getMaximumSamplesPerRay()) {
|
|
473
473
|
vtkWarningMacro("The number of steps required ".concat(Math.ceil(maxSamples), " is larger than the\n specified maximum number of steps ").concat(model.renderable.getMaximumSamplesPerRay(), ".\n Please either change the\n volumeMapper sampleDistance or its maximum number of samples."));
|
|
@@ -817,8 +817,25 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
817
817
|
return [lowerLeftU, lowerLeftV];
|
|
818
818
|
};
|
|
819
819
|
|
|
820
|
+
publicAPI.getCurrentSampleDistance = function (ren) {
|
|
821
|
+
var rwi = ren.getVTKWindow().getInteractor();
|
|
822
|
+
var baseSampleDistance = model.renderable.getSampleDistance();
|
|
823
|
+
|
|
824
|
+
if (rwi.isAnimating()) {
|
|
825
|
+
var factor = model.renderable.getInteractionSampleDistanceFactor();
|
|
826
|
+
return baseSampleDistance * factor;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
return baseSampleDistance;
|
|
830
|
+
};
|
|
831
|
+
|
|
820
832
|
publicAPI.renderPieceStart = function (ren, actor) {
|
|
821
833
|
var rwi = ren.getVTKWindow().getInteractor();
|
|
834
|
+
|
|
835
|
+
if (!model._lastScale) {
|
|
836
|
+
model._lastScale = model.renderable.getInitialInteractionScale();
|
|
837
|
+
}
|
|
838
|
+
|
|
822
839
|
model._useSmallViewport = false;
|
|
823
840
|
|
|
824
841
|
if (rwi.isAnimating() && model._lastScale > 1.5) {
|
|
@@ -849,18 +866,16 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
849
866
|
} else {
|
|
850
867
|
model._lastScale = model.renderable.getImageSampleDistance() * model.renderable.getImageSampleDistance();
|
|
851
868
|
}
|
|
852
|
-
|
|
853
|
-
var size = model._openGLRenderWindow.getFramebufferSize();
|
|
854
|
-
|
|
855
|
-
model._smallViewportWidth = Math.ceil(size[0] / Math.sqrt(model._lastScale));
|
|
856
|
-
model._smallViewportHeight = Math.ceil(size[1] / Math.sqrt(model._lastScale));
|
|
857
869
|
});
|
|
858
870
|
} // use/create/resize framebuffer if needed
|
|
859
871
|
|
|
860
872
|
|
|
861
873
|
if (model._useSmallViewport) {
|
|
862
|
-
var size = model._openGLRenderWindow.getFramebufferSize();
|
|
874
|
+
var size = model._openGLRenderWindow.getFramebufferSize();
|
|
863
875
|
|
|
876
|
+
var scaleFactor = 1 / Math.sqrt(model._lastScale);
|
|
877
|
+
model._smallViewportWidth = Math.ceil(scaleFactor * size[0]);
|
|
878
|
+
model._smallViewportHeight = Math.ceil(scaleFactor * size[1]); // adjust viewportSize to always be at most the dest fo size
|
|
864
879
|
|
|
865
880
|
if (model._smallViewportHeight > size[1]) {
|
|
866
881
|
model._smallViewportHeight = size[1];
|
|
@@ -1063,7 +1078,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
1063
1078
|
|
|
1064
1079
|
for (var c = 0; c < numIComps; ++c) {
|
|
1065
1080
|
var ofun = vprop.getScalarOpacity(c);
|
|
1066
|
-
var opacityFactor =
|
|
1081
|
+
var opacityFactor = publicAPI.getCurrentSampleDistance(ren) / vprop.getScalarOpacityUnitDistance(c);
|
|
1067
1082
|
var oRange = ofun.getRange();
|
|
1068
1083
|
ofun.getTable(oRange[0], oRange[1], oWidth, tmpTable, 1); // adjust for sample distance etc
|
|
1069
1084
|
|
|
@@ -1251,8 +1266,7 @@ function extend(publicAPI, model) {
|
|
|
1251
1266
|
model.idxNormalMatrix = mat3.identity(new Float64Array(9));
|
|
1252
1267
|
model.modelToView = mat4.identity(new Float64Array(16));
|
|
1253
1268
|
model.projectionToView = mat4.identity(new Float64Array(16));
|
|
1254
|
-
model.projectionToWorld = mat4.identity(new Float64Array(16));
|
|
1255
|
-
model._lastScale = 1.0; // Build VTK API
|
|
1269
|
+
model.projectionToWorld = mat4.identity(new Float64Array(16)); // Build VTK API
|
|
1256
1270
|
|
|
1257
1271
|
setGet(publicAPI, model, ['context']); // Object methods
|
|
1258
1272
|
|
|
@@ -187,15 +187,16 @@ function vtkWebGPUVolumePass(publicAPI, model) {
|
|
|
187
187
|
}, publicAPI.delete);
|
|
188
188
|
|
|
189
189
|
publicAPI.computeTiming = function (viewNode) {
|
|
190
|
-
model._useSmallViewport = false;
|
|
191
190
|
var rwi = viewNode.getRenderable().getInteractor();
|
|
192
191
|
|
|
193
|
-
if (
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
192
|
+
if (model._lastScale == null) {
|
|
193
|
+
var firstMapper = model.volumes[0].getRenderable().getMapper();
|
|
194
|
+
model._lastScale = firstMapper.getInitialInteractionScale() || 1.0;
|
|
195
|
+
}
|
|
198
196
|
|
|
197
|
+
model._useSmallViewport = false;
|
|
198
|
+
|
|
199
|
+
if (rwi.isAnimating() && model._lastScale > 1.5) {
|
|
199
200
|
model._useSmallViewport = true;
|
|
200
201
|
}
|
|
201
202
|
|
|
@@ -222,9 +223,6 @@ function vtkWebGPUVolumePass(publicAPI, model) {
|
|
|
222
223
|
|
|
223
224
|
if (model._lastScale < 1.5) {
|
|
224
225
|
model._lastScale = 1.5;
|
|
225
|
-
} else {
|
|
226
|
-
model._smallViewportWidth = Math.ceil(viewNode.getCanvas().width / Math.sqrt(model._lastScale));
|
|
227
|
-
model._smallViewportHeight = Math.ceil(viewNode.getCanvas().height / Math.sqrt(model._lastScale));
|
|
228
226
|
}
|
|
229
227
|
});
|
|
230
228
|
}
|
|
@@ -240,6 +238,10 @@ function vtkWebGPUVolumePass(publicAPI, model) {
|
|
|
240
238
|
var height = model._colorTextureView.getTexture().getHeight();
|
|
241
239
|
|
|
242
240
|
if (model._useSmallViewport) {
|
|
241
|
+
var canvas = viewNode.getCanvas();
|
|
242
|
+
var scaleFactor = 1 / Math.sqrt(model._lastScale);
|
|
243
|
+
model._smallViewportWidth = Math.ceil(scaleFactor * canvas.width);
|
|
244
|
+
model._smallViewportHeight = Math.ceil(scaleFactor * canvas.height);
|
|
243
245
|
width = model._smallViewportWidth;
|
|
244
246
|
height = model._smallViewportHeight;
|
|
245
247
|
}
|
|
@@ -655,7 +657,6 @@ function extend(publicAPI, model) {
|
|
|
655
657
|
Object.assign(model, DEFAULT_VALUES, initialValues); // Build VTK API
|
|
656
658
|
|
|
657
659
|
vtkRenderPass.extend(publicAPI, model, initialValues);
|
|
658
|
-
model._lastScale = 2.0;
|
|
659
660
|
model._mapper = vtkWebGPUSimpleMapper.newInstance();
|
|
660
661
|
|
|
661
662
|
model._mapper.setFragmentShaderTemplate(DepthBoundsFS);
|