@kitware/vtk.js 32.6.2 → 33.0.0-beta.2
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/BREAKING_CHANGES.md +3 -0
- package/IO/Image.js +1 -3
- package/Interaction/Manipulators/KeyboardCameraManipulator.d.ts +113 -0
- package/Rendering/Core/Actor.d.ts +5 -20
- package/Rendering/Core/Actor.js +5 -68
- package/Rendering/Core/ImageProperty.d.ts +0 -22
- package/Rendering/Core/ImageSlice.d.ts +7 -23
- package/Rendering/Core/ImageSlice.js +9 -68
- package/Rendering/Core/PointPicker.js +1 -4
- package/Rendering/Core/Prop3D.d.ts +39 -2
- package/Rendering/Core/Prop3D.js +81 -2
- package/Rendering/Core/RenderWindowInteractor.d.ts +1 -1
- package/Rendering/Core/Volume.d.ts +5 -20
- package/Rendering/Core/Volume.js +2 -70
- package/Rendering/Core/VolumeMapper/Constants.d.ts +0 -7
- package/Rendering/Core/VolumeMapper/Constants.js +2 -8
- package/Rendering/Core/VolumeMapper.d.ts +16 -140
- package/Rendering/Core/VolumeMapper.js +17 -52
- package/Rendering/Core/VolumeProperty/Constants.d.ts +12 -3
- package/Rendering/Core/VolumeProperty/Constants.js +11 -4
- package/Rendering/Core/VolumeProperty.d.ts +120 -4
- package/Rendering/Core/VolumeProperty.js +49 -4
- package/Rendering/OpenGL/ImageCPRMapper.js +27 -19
- package/Rendering/OpenGL/ImageMapper.js +34 -41
- package/Rendering/OpenGL/ImageResliceMapper.js +261 -172
- package/Rendering/OpenGL/PolyDataMapper.js +1 -8
- package/Rendering/OpenGL/RenderWindow/resourceSharingHelper.d.ts +3 -3
- package/Rendering/OpenGL/RenderWindow/resourceSharingHelper.js +8 -5
- package/Rendering/OpenGL/VolumeMapper.js +710 -772
- package/Rendering/OpenGL/glsl/vtkVolumeFS.glsl.js +1 -1
- package/Rendering/WebGPU/VolumePassFSQ.js +2 -2
- package/index.d.ts +1 -1
- package/macros2.js +1 -1
- package/package.json +1 -1
- package/IO/Image/TGAReader/Constants.js +0 -28
- package/IO/Image/TGAReader.d.ts +0 -121
- package/IO/Image/TGAReader.js +0 -418
|
@@ -13,6 +13,7 @@ export interface IVolumePropertyInitialValues {
|
|
|
13
13
|
specularPower?: number;
|
|
14
14
|
useLabelOutline?: boolean;
|
|
15
15
|
labelOutlineThickness?: number | number[];
|
|
16
|
+
colorMixPreset?: ColorMixPreset;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export interface vtkVolumeProperty extends vtkObject {
|
|
@@ -71,7 +72,7 @@ export interface vtkVolumeProperty extends vtkObject {
|
|
|
71
72
|
/**
|
|
72
73
|
*
|
|
73
74
|
*/
|
|
74
|
-
getColorMixPreset():
|
|
75
|
+
getColorMixPreset(): ColorMixPreset;
|
|
75
76
|
|
|
76
77
|
/**
|
|
77
78
|
*
|
|
@@ -194,7 +195,7 @@ export interface vtkVolumeProperty extends vtkObject {
|
|
|
194
195
|
|
|
195
196
|
/**
|
|
196
197
|
* Set the color mix code to a preset value
|
|
197
|
-
*
|
|
198
|
+
* Defaults to ColorMixPreset.DEFAULT
|
|
198
199
|
* See the test `testColorMix` for an example on how to use this preset.
|
|
199
200
|
*
|
|
200
201
|
* If set to `CUSTOM`, a tag `//VTK::CustomColorMix` is made available to the
|
|
@@ -202,9 +203,9 @@ export interface vtkVolumeProperty extends vtkObject {
|
|
|
202
203
|
* will be used to mix the colors from each component.
|
|
203
204
|
* Each component is available as a rgba vec4: `comp0`, `comp1`...
|
|
204
205
|
* There are other useful functions or variable available. To find them,
|
|
205
|
-
* see `//VTK::
|
|
206
|
+
* see `//VTK::CustomColorMix` tag in `vtkVolumeFS.glsl`.
|
|
206
207
|
*/
|
|
207
|
-
setColorMixPreset(preset:
|
|
208
|
+
setColorMixPreset(preset: ColorMixPreset): boolean;
|
|
208
209
|
|
|
209
210
|
/**
|
|
210
211
|
* Does the data have independent components, or do some define color only?
|
|
@@ -370,6 +371,121 @@ export interface vtkVolumeProperty extends vtkObject {
|
|
|
370
371
|
* Get the interpolation type for sampling a volume as a string.
|
|
371
372
|
*/
|
|
372
373
|
getInterpolationTypeAsString(): string;
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
*
|
|
377
|
+
*/
|
|
378
|
+
getAverageIPScalarRange(): Range;
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
*
|
|
382
|
+
*/
|
|
383
|
+
getAverageIPScalarRangeByReference(): Range;
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Get the blending coefficient that interpolates between surface and volume rendering
|
|
387
|
+
* @default 0.0
|
|
388
|
+
*/
|
|
389
|
+
getVolumetricScatteringBlending(): number;
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Get the global illumination reach of volume shadow
|
|
393
|
+
* @default 0.0
|
|
394
|
+
*/
|
|
395
|
+
getGlobalIlluminationReach(): number;
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Get anisotropy of volume shadow scatter
|
|
399
|
+
* @default 0.0
|
|
400
|
+
*/
|
|
401
|
+
getAnisotropy(): number;
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Get local ambient occlusion flag
|
|
405
|
+
* @default false
|
|
406
|
+
*/
|
|
407
|
+
getLocalAmbientOcclusion(): boolean;
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Get kernel size for local ambient occlusion
|
|
411
|
+
* @default 15
|
|
412
|
+
*/
|
|
413
|
+
getLAOKernelSize(): number;
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Get kernel radius for local ambient occlusion
|
|
417
|
+
* @default 7
|
|
418
|
+
*/
|
|
419
|
+
getLAOKernelRadius(): number;
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
*
|
|
423
|
+
* @param x
|
|
424
|
+
* @param y
|
|
425
|
+
*/
|
|
426
|
+
setAverageIPScalarRange(x: number, y: number): boolean;
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
*
|
|
430
|
+
* @param {Range} averageIPScalarRange
|
|
431
|
+
*/
|
|
432
|
+
setAverageIPScalarRangeFrom(averageIPScalarRange: Range): boolean;
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Set the normal computation to be dependent on the transfer function.
|
|
436
|
+
* By default, the mapper relies on the scalar gradient for computing normals at sample locations
|
|
437
|
+
* for lighting calculations. This is an approximation and can lead to inaccurate results.
|
|
438
|
+
* When enabled, this property makes the mapper compute normals based on the accumulated opacity
|
|
439
|
+
* at sample locations. This can generate a more accurate representation of edge structures in the
|
|
440
|
+
* data but adds an overhead and drops frame rate.
|
|
441
|
+
* @param computeNormalFromOpacity
|
|
442
|
+
*/
|
|
443
|
+
setComputeNormalFromOpacity(computeNormalFromOpacity: boolean): boolean;
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Set the blending coefficient that determines the interpolation between surface and volume rendering.
|
|
447
|
+
* Default value of 0.0 means shadow effect is computed with phong model.
|
|
448
|
+
* Value of 1.0 means shadow is created by volume occlusion.
|
|
449
|
+
* @param volumeScatterBlendCoef
|
|
450
|
+
*/
|
|
451
|
+
setVolumetricScatteringBlending(volumeScatterBlendCoef: number): void;
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Set the global illumination reach of volume shadow. This function is only effective when volumeScatterBlendCoef is greater than 0.
|
|
455
|
+
* Default value of 0.0 means only the neighboring voxel is considered when creating global shadow.
|
|
456
|
+
* Value of 1.0 means the shadow ray traverses through the entire volume.
|
|
457
|
+
* @param globalIlluminationReach
|
|
458
|
+
*/
|
|
459
|
+
setGlobalIlluminationReach(globalIlluminationReach: number): void;
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Set anisotropy of volume shadow scatter. This function is only effective when volumeScatterBlendCoef is greater than 0.
|
|
463
|
+
* Default value of 0.0 means light scatters uniformly in all directions.
|
|
464
|
+
* Value of -1.0 means light scatters backward, value of 1.0 means light scatters forward.
|
|
465
|
+
* @param anisotropy
|
|
466
|
+
*/
|
|
467
|
+
setAnisotropy(anisotropy: number): void;
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Set whether to turn on local ambient occlusion (LAO). LAO is only effective if shading is on and volumeScatterBlendCoef is set to 0.
|
|
471
|
+
* LAO effect is added to ambient lighting, so the ambient component of the actor needs to be great than 0.
|
|
472
|
+
* @param localAmbientOcclusion
|
|
473
|
+
*/
|
|
474
|
+
setLocalAmbientOcclusion(localAmbientOcclusion: boolean): void;
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Set kernel size for local ambient occlusion. It specifies the number of rays that are randomly sampled in the hemisphere.
|
|
478
|
+
* Value is clipped between 1 and 32.
|
|
479
|
+
* @param LAOKernelSize
|
|
480
|
+
*/
|
|
481
|
+
setLAOKernelSize(LAOKernelSize: number): void;
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Set kernel radius for local ambient occlusion. It specifies the number of samples that are considered on each random ray.
|
|
485
|
+
* Value must be greater than or equal to 1.
|
|
486
|
+
* @param LAOKernelRadius
|
|
487
|
+
*/
|
|
488
|
+
setLAOKernelRadius(LAOKernelRadius: number): void;
|
|
373
489
|
}
|
|
374
490
|
|
|
375
491
|
/**
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { m as macro } from '../../macros2.js';
|
|
2
|
+
import { E as clampValue, K as floor } from '../../Common/Core/Math/index.js';
|
|
2
3
|
import vtkColorTransferFunction from './ColorTransferFunction.js';
|
|
3
4
|
import vtkPiecewiseFunction from '../../Common/DataModel/PiecewiseFunction.js';
|
|
4
5
|
import Constants from './VolumeProperty/Constants.js';
|
|
5
6
|
|
|
6
7
|
const {
|
|
7
8
|
InterpolationType,
|
|
8
|
-
OpacityMode
|
|
9
|
+
OpacityMode,
|
|
10
|
+
FilterMode,
|
|
11
|
+
ColorMixPreset
|
|
9
12
|
} = Constants;
|
|
10
13
|
const {
|
|
11
14
|
vtkErrorMacro
|
|
@@ -19,6 +22,9 @@ const VTK_MAX_VRCOMP = 4;
|
|
|
19
22
|
function vtkVolumeProperty(publicAPI, model) {
|
|
20
23
|
// Set our className
|
|
21
24
|
model.classHierarchy.push('vtkVolumeProperty');
|
|
25
|
+
const superClass = {
|
|
26
|
+
...publicAPI
|
|
27
|
+
};
|
|
22
28
|
publicAPI.getMTime = () => {
|
|
23
29
|
let mTime = model.mtime;
|
|
24
30
|
let time;
|
|
@@ -197,6 +203,25 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
197
203
|
const cap = macro.capitalize(val);
|
|
198
204
|
publicAPI[`get${cap}`] = index => model.componentData[index][`${val}`];
|
|
199
205
|
});
|
|
206
|
+
publicAPI.setAverageIPScalarRange = (min, max) => {
|
|
207
|
+
console.warn('setAverageIPScalarRange is deprecated use setIpScalarRange');
|
|
208
|
+
publicAPI.setIpScalarRange(min, max);
|
|
209
|
+
};
|
|
210
|
+
publicAPI.getFilterModeAsString = () => macro.enumToString(FilterMode, model.filterMode);
|
|
211
|
+
publicAPI.setFilterModeToOff = () => {
|
|
212
|
+
publicAPI.setFilterMode(FilterMode.OFF);
|
|
213
|
+
};
|
|
214
|
+
publicAPI.setFilterModeToNormalized = () => {
|
|
215
|
+
publicAPI.setFilterMode(FilterMode.NORMALIZED);
|
|
216
|
+
};
|
|
217
|
+
publicAPI.setFilterModeToRaw = () => {
|
|
218
|
+
publicAPI.setFilterMode(FilterMode.RAW);
|
|
219
|
+
};
|
|
220
|
+
publicAPI.setGlobalIlluminationReach = gl => superClass.setGlobalIlluminationReach(clampValue(gl, 0.0, 1.0));
|
|
221
|
+
publicAPI.setVolumetricScatteringBlending = vsb => superClass.setVolumetricScatteringBlending(clampValue(vsb, 0.0, 1.0));
|
|
222
|
+
publicAPI.setAnisotropy = at => superClass.setAnisotropy(clampValue(at, -0.99, 0.99));
|
|
223
|
+
publicAPI.setLAOKernelSize = ks => superClass.setLAOKernelSize(floor(clampValue(ks, 1, 32)));
|
|
224
|
+
publicAPI.setLAOKernelRadius = kr => superClass.setLAOKernelRadius(kr >= 1 ? kr : 1);
|
|
200
225
|
}
|
|
201
226
|
|
|
202
227
|
// ----------------------------------------------------------------------------
|
|
@@ -204,7 +229,7 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
204
229
|
// ----------------------------------------------------------------------------
|
|
205
230
|
|
|
206
231
|
const DEFAULT_VALUES = {
|
|
207
|
-
colorMixPreset:
|
|
232
|
+
colorMixPreset: ColorMixPreset.DEFAULT,
|
|
208
233
|
independentComponents: true,
|
|
209
234
|
interpolationType: InterpolationType.FAST_LINEAR,
|
|
210
235
|
shade: false,
|
|
@@ -214,7 +239,22 @@ const DEFAULT_VALUES = {
|
|
|
214
239
|
specularPower: 10.0,
|
|
215
240
|
useLabelOutline: false,
|
|
216
241
|
labelOutlineThickness: [1],
|
|
217
|
-
labelOutlineOpacity: 1.0
|
|
242
|
+
labelOutlineOpacity: 1.0,
|
|
243
|
+
// Properties moved from volume mapper
|
|
244
|
+
ipScalarRange: [-1000000.0, 1000000.0],
|
|
245
|
+
filterMode: FilterMode.OFF,
|
|
246
|
+
// ignored by WebGL so no behavior change
|
|
247
|
+
preferSizeOverAccuracy: false,
|
|
248
|
+
// Whether to use halfFloat representation of float, when it is inaccurate
|
|
249
|
+
computeNormalFromOpacity: false,
|
|
250
|
+
// volume shadow parameters
|
|
251
|
+
volumetricScatteringBlending: 0.0,
|
|
252
|
+
globalIlluminationReach: 0.0,
|
|
253
|
+
anisotropy: 0.0,
|
|
254
|
+
// local ambient occlusion
|
|
255
|
+
localAmbientOcclusion: false,
|
|
256
|
+
LAOKernelSize: 15,
|
|
257
|
+
LAOKernelRadius: 7
|
|
218
258
|
};
|
|
219
259
|
|
|
220
260
|
// ----------------------------------------------------------------------------
|
|
@@ -245,7 +285,12 @@ function extend(publicAPI, model) {
|
|
|
245
285
|
});
|
|
246
286
|
}
|
|
247
287
|
}
|
|
248
|
-
macro.setGet(publicAPI, model, ['colorMixPreset', 'independentComponents', 'interpolationType', 'shade', 'ambient', 'diffuse', 'specular', 'specularPower', 'useLabelOutline', 'labelOutlineOpacity'
|
|
288
|
+
macro.setGet(publicAPI, model, ['colorMixPreset', 'independentComponents', 'interpolationType', 'shade', 'ambient', 'diffuse', 'specular', 'specularPower', 'useLabelOutline', 'labelOutlineOpacity',
|
|
289
|
+
// Properties moved from volume mapper
|
|
290
|
+
'filterMode', 'preferSizeOverAccuracy', 'computeNormalFromOpacity', 'volumetricScatteringBlending', 'globalIlluminationReach', 'anisotropy', 'localAmbientOcclusion', 'LAOKernelSize', 'LAOKernelRadius']);
|
|
291
|
+
|
|
292
|
+
// Property moved from volume mapper
|
|
293
|
+
macro.setGetArray(publicAPI, model, ['ipScalarRange'], 2);
|
|
249
294
|
macro.setGetArray(publicAPI, model, ['labelOutlineThickness']);
|
|
250
295
|
|
|
251
296
|
// Object methods
|
|
@@ -11,7 +11,7 @@ import vtkOpenGLTexture from './Texture.js';
|
|
|
11
11
|
import vtkReplacementShaderMapper from './ReplacementShaderMapper.js';
|
|
12
12
|
import vtkShaderProgram from './ShaderProgram.js';
|
|
13
13
|
import vtkViewNode from '../SceneGraph/ViewNode.js';
|
|
14
|
-
import { getImageDataHash,
|
|
14
|
+
import { getImageDataHash, getTransferFunctionsHash } from './RenderWindow/resourceSharingHelper.js';
|
|
15
15
|
import { v as vtkPolyDataVS } from './glsl/vtkPolyDataVS.glsl.js';
|
|
16
16
|
import { v as vtkPolyDataFS } from './glsl/vtkPolyDataFS.glsl.js';
|
|
17
17
|
import { registerOverride } from './ViewNodeFactory.js';
|
|
@@ -181,9 +181,13 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
|
|
|
181
181
|
const iComps = ppty.getIndependentComponents();
|
|
182
182
|
const numIComps = iComps ? numComp : 1;
|
|
183
183
|
const textureHeight = iComps ? 2 * numIComps : 1;
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
const colorTransferFunctions = [];
|
|
185
|
+
for (let component = 0; component < numIComps; ++component) {
|
|
186
|
+
colorTransferFunctions.push(ppty.getRGBTransferFunction(component));
|
|
187
|
+
}
|
|
188
|
+
const colorTextureHash = getTransferFunctionsHash(colorTransferFunctions, iComps, numIComps);
|
|
189
|
+
const firstColorTransferFunc = ppty.getRGBTransferFunction();
|
|
190
|
+
const cachedColorEntry = model._openGLRenderWindow.getGraphicsResourceForObject(firstColorTransferFunc);
|
|
187
191
|
const reBuildColorTexture = !cachedColorEntry?.oglObject?.getHandle() || cachedColorEntry?.hash !== colorTextureHash;
|
|
188
192
|
if (reBuildColorTexture) {
|
|
189
193
|
const cWidth = 1024;
|
|
@@ -191,7 +195,7 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
|
|
|
191
195
|
const cTable = new Uint8ClampedArray(cSize);
|
|
192
196
|
model.colorTexture = vtkOpenGLTexture.newInstance();
|
|
193
197
|
model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
194
|
-
if (
|
|
198
|
+
if (firstColorTransferFunc) {
|
|
195
199
|
const tmpTable = new Float32Array(cWidth * 3);
|
|
196
200
|
for (let c = 0; c < numIComps; c++) {
|
|
197
201
|
const cfun = ppty.getRGBTransferFunction(c);
|
|
@@ -219,13 +223,13 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
|
|
|
219
223
|
model.colorTexture.resetFormatAndType();
|
|
220
224
|
model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
221
225
|
}
|
|
222
|
-
if (
|
|
223
|
-
model._openGLRenderWindow.setGraphicsResourceForObject(
|
|
224
|
-
if (
|
|
225
|
-
model._openGLRenderWindow.registerGraphicsResourceUser(
|
|
226
|
+
if (firstColorTransferFunc) {
|
|
227
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(firstColorTransferFunc, model.colorTexture, colorTextureHash);
|
|
228
|
+
if (firstColorTransferFunc !== model._colorTransferFunc) {
|
|
229
|
+
model._openGLRenderWindow.registerGraphicsResourceUser(firstColorTransferFunc, publicAPI);
|
|
226
230
|
model._openGLRenderWindow.unregisterGraphicsResourceUser(model._colorTransferFunc, publicAPI);
|
|
227
231
|
}
|
|
228
|
-
model._colorTransferFunc =
|
|
232
|
+
model._colorTransferFunc = firstColorTransferFunc;
|
|
229
233
|
}
|
|
230
234
|
} else {
|
|
231
235
|
model.colorTexture = cachedColorEntry.oglObject;
|
|
@@ -234,9 +238,13 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
|
|
|
234
238
|
// Build piecewise function buffer. This buffer is used either
|
|
235
239
|
// for component weighting or opacity, depending on whether we're
|
|
236
240
|
// rendering components independently or not.
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
241
|
+
const opacityFunctions = [];
|
|
242
|
+
for (let component = 0; component < numIComps; ++component) {
|
|
243
|
+
opacityFunctions.push(ppty.getPiecewiseFunction(component));
|
|
244
|
+
}
|
|
245
|
+
const pwfTextureHash = getTransferFunctionsHash(opacityFunctions, iComps, numIComps);
|
|
246
|
+
const firstPwFunc = ppty.getPiecewiseFunction();
|
|
247
|
+
const cachedPwfEntry = model._openGLRenderWindow.getGraphicsResourceForObject(firstPwFunc);
|
|
240
248
|
const reBuildPwf = !cachedPwfEntry?.oglObject?.getHandle() || cachedPwfEntry?.hash !== pwfTextureHash;
|
|
241
249
|
if (reBuildPwf) {
|
|
242
250
|
const pwfWidth = 1024;
|
|
@@ -244,7 +252,7 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
|
|
|
244
252
|
const pwfTable = new Uint8ClampedArray(pwfSize);
|
|
245
253
|
model.pwfTexture = vtkOpenGLTexture.newInstance();
|
|
246
254
|
model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
247
|
-
if (
|
|
255
|
+
if (firstPwFunc) {
|
|
248
256
|
const pwfFloatTable = new Float32Array(pwfSize);
|
|
249
257
|
const tmpTable = new Float32Array(pwfWidth);
|
|
250
258
|
for (let c = 0; c < numIComps; ++c) {
|
|
@@ -276,13 +284,13 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
|
|
|
276
284
|
model.pwfTexture.resetFormatAndType();
|
|
277
285
|
model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable);
|
|
278
286
|
}
|
|
279
|
-
if (
|
|
280
|
-
model._openGLRenderWindow.setGraphicsResourceForObject(
|
|
281
|
-
if (
|
|
282
|
-
model._openGLRenderWindow.registerGraphicsResourceUser(
|
|
287
|
+
if (firstPwFunc) {
|
|
288
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(firstPwFunc, model.pwfTexture, pwfTextureHash);
|
|
289
|
+
if (firstPwFunc !== model._pwFunc) {
|
|
290
|
+
model._openGLRenderWindow.registerGraphicsResourceUser(firstPwFunc, publicAPI);
|
|
283
291
|
model._openGLRenderWindow.unregisterGraphicsResourceUser(model._pwFunc, publicAPI);
|
|
284
292
|
}
|
|
285
|
-
model._pwFunc =
|
|
293
|
+
model._pwFunc = firstPwFunc;
|
|
286
294
|
}
|
|
287
295
|
} else {
|
|
288
296
|
model.pwfTexture = cachedPwfEntry.oglObject;
|
|
@@ -4,14 +4,13 @@ import { n as newInstance$1, e as setGet, o as obj, r as vtkErrorMacro$1, h as c
|
|
|
4
4
|
import vtkDataArray from '../../Common/Core/DataArray.js';
|
|
5
5
|
import { VtkDataTypes } from '../../Common/Core/DataArray/Constants.js';
|
|
6
6
|
import vtkHelper from './Helper.js';
|
|
7
|
-
import { u as uninitializeBounds } from '../../Common/Core/Math/index.js';
|
|
8
7
|
import vtkOpenGLTexture from './Texture.js';
|
|
9
8
|
import vtkShaderProgram from './ShaderProgram.js';
|
|
10
9
|
import vtkViewNode from '../SceneGraph/ViewNode.js';
|
|
11
10
|
import { Representation } from '../Core/Property/Constants.js';
|
|
12
11
|
import { Filter, Wrap } from './Texture/Constants.js';
|
|
13
12
|
import { InterpolationType } from '../Core/ImageProperty/Constants.js';
|
|
14
|
-
import {
|
|
13
|
+
import { getTransferFunctionsHash } from './RenderWindow/resourceSharingHelper.js';
|
|
15
14
|
import { v as vtkPolyDataVS } from './glsl/vtkPolyDataVS.glsl.js';
|
|
16
15
|
import { v as vtkPolyDataFS } from './glsl/vtkPolyDataFS.glsl.js';
|
|
17
16
|
import vtkReplacementShaderMapper from './ReplacementShaderMapper.js';
|
|
@@ -168,9 +167,9 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
168
167
|
// check for the outline thickness and opacity
|
|
169
168
|
const vtkImageLabelOutline = actor.getProperty().getUseLabelOutline();
|
|
170
169
|
if (vtkImageLabelOutline === true) {
|
|
171
|
-
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::LabelOutline::Dec', ['uniform int outlineThickness;', 'uniform float vpWidth;', 'uniform float vpHeight;', 'uniform float vpOffsetX;', 'uniform float vpOffsetY;', 'uniform mat4 PCWCMatrix;', 'uniform mat4 vWCtoIDX;', 'uniform ivec3 imageDimensions;'
|
|
170
|
+
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::LabelOutline::Dec', ['uniform int outlineThickness;', 'uniform float vpWidth;', 'uniform float vpHeight;', 'uniform float vpOffsetX;', 'uniform float vpOffsetY;', 'uniform mat4 PCWCMatrix;', 'uniform mat4 vWCtoIDX;', 'uniform ivec3 imageDimensions;']).result;
|
|
172
171
|
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ImageLabelOutlineOn', '#define vtkImageLabelOutlineOn').result;
|
|
173
|
-
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::LabelOutlineHelperFunction', ['#ifdef vtkImageLabelOutlineOn', 'vec3 fragCoordToIndexSpace(vec4 fragCoord) {', ' vec4 pcPos = vec4(', ' (fragCoord.x / vpWidth - vpOffsetX - 0.5) * 2.0,', ' (fragCoord.y / vpHeight - vpOffsetY - 0.5) * 2.0,', ' (fragCoord.z - 0.5) * 2.0,', ' 1.0);', '', ' vec4 worldCoord = PCWCMatrix * pcPos;', ' vec4 vertex = (worldCoord/worldCoord.w);', '', ' vec3 index = (vWCtoIDX * vertex).xyz;', '', ' // half voxel fix for labelmapOutline', ' return (index + vec3(0.5)) / vec3(imageDimensions);', '}', '
|
|
172
|
+
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::LabelOutlineHelperFunction', ['#ifdef vtkImageLabelOutlineOn', 'vec3 fragCoordToIndexSpace(vec4 fragCoord) {', ' vec4 pcPos = vec4(', ' (fragCoord.x / vpWidth - vpOffsetX - 0.5) * 2.0,', ' (fragCoord.y / vpHeight - vpOffsetY - 0.5) * 2.0,', ' (fragCoord.z - 0.5) * 2.0,', ' 1.0);', '', ' vec4 worldCoord = PCWCMatrix * pcPos;', ' vec4 vertex = (worldCoord/worldCoord.w);', '', ' vec3 index = (vWCtoIDX * vertex).xyz;', '', ' // half voxel fix for labelmapOutline', ' return (index + vec3(0.5)) / vec3(imageDimensions);', '}', '#endif']).result;
|
|
174
173
|
}
|
|
175
174
|
if (iComps) {
|
|
176
175
|
const rgba = ['r', 'g', 'b', 'a'];
|
|
@@ -202,7 +201,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
202
201
|
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', [...splitStringOnEnter(`
|
|
203
202
|
#ifdef vtkImageLabelOutlineOn
|
|
204
203
|
vec3 centerPosIS = fragCoordToIndexSpace(gl_FragCoord);
|
|
205
|
-
float centerValue = texture2D(texture1,
|
|
204
|
+
float centerValue = texture2D(texture1, centerPosIS.xy).r;
|
|
206
205
|
bool pixelOnBorder = false;
|
|
207
206
|
vec3 tColor = texture2D(colorTexture1, vec2(centerValue * cscale0 + cshift0, 0.5)).rgb;
|
|
208
207
|
float scalarOpacity = texture2D(pwfTexture1, vec2(centerValue * pwfscale0 + pwfshift0, 0.5)).r;
|
|
@@ -213,7 +212,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
213
212
|
int actualThickness = int(textureValue * 255.0);
|
|
214
213
|
|
|
215
214
|
if (segmentIndex == 0){
|
|
216
|
-
gl_FragData[0] = vec4(0.0,
|
|
215
|
+
gl_FragData[0] = vec4(0.0, 1.0, 1.0, 0.0);
|
|
217
216
|
return;
|
|
218
217
|
}
|
|
219
218
|
|
|
@@ -226,7 +225,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
226
225
|
gl_FragCoord.y + float(j),
|
|
227
226
|
gl_FragCoord.z, gl_FragCoord.w);
|
|
228
227
|
vec3 neighborPosIS = fragCoordToIndexSpace(neighborPixelCoord);
|
|
229
|
-
float value = texture2D(texture1,
|
|
228
|
+
float value = texture2D(texture1, neighborPosIS.xy).r;
|
|
230
229
|
if (value != centerValue) {
|
|
231
230
|
pixelOnBorder = true;
|
|
232
231
|
break;
|
|
@@ -475,14 +474,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
475
474
|
if (vtkImageLabelOutline === true) {
|
|
476
475
|
const worldToIndex = image.getWorldToIndex();
|
|
477
476
|
const imageDimensions = image.getDimensions();
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
// SlicingMode.NONE equates to SlicingMode.K
|
|
481
|
-
if (sliceAxis === SlicingMode.NONE) {
|
|
482
|
-
sliceAxis = SlicingMode.K;
|
|
483
|
-
}
|
|
484
|
-
program.setUniform3i('imageDimensions', imageDimensions[0], imageDimensions[1], imageDimensions[2]);
|
|
485
|
-
program.setUniformi('sliceAxis', sliceAxis);
|
|
477
|
+
program.setUniform3i('imageDimensions', imageDimensions[0], imageDimensions[1], 1);
|
|
486
478
|
program.setUniformMatrix('vWCtoIDX', worldToIndex);
|
|
487
479
|
const labelOutlineKeyMats = model.openGLCamera.getKeyMatrices(ren);
|
|
488
480
|
|
|
@@ -555,13 +547,6 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
555
547
|
publicAPI.renderPieceDraw(ren, actor);
|
|
556
548
|
publicAPI.renderPieceFinish(ren, actor);
|
|
557
549
|
};
|
|
558
|
-
publicAPI.computeBounds = (ren, actor) => {
|
|
559
|
-
if (!publicAPI.getInput()) {
|
|
560
|
-
uninitializeBounds(model.bounds);
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
model.bounds = publicAPI.getInput().getBounds();
|
|
564
|
-
};
|
|
565
550
|
publicAPI.updateBufferObjects = (ren, actor) => {
|
|
566
551
|
// Rebuild buffers if needed
|
|
567
552
|
if (publicAPI.getNeedToRebuildBufferObjects(ren, actor)) {
|
|
@@ -585,9 +570,13 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
585
570
|
const iComps = actorProperty.getIndependentComponents();
|
|
586
571
|
const numIComps = iComps ? numComp : 1;
|
|
587
572
|
const textureHeight = iComps ? 2 * numIComps : 1;
|
|
588
|
-
const
|
|
589
|
-
|
|
590
|
-
|
|
573
|
+
const colorTransferFunctions = [];
|
|
574
|
+
for (let component = 0; component < numIComps; ++component) {
|
|
575
|
+
colorTransferFunctions.push(actorProperty.getRGBTransferFunction(component));
|
|
576
|
+
}
|
|
577
|
+
const cfunToString = getTransferFunctionsHash(colorTransferFunctions, iComps, numIComps);
|
|
578
|
+
const firstColorTransferFunc = actorProperty.getRGBTransferFunction();
|
|
579
|
+
const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(firstColorTransferFunc);
|
|
591
580
|
const reBuildC = !cTex?.oglObject?.getHandle() || cTex?.hash !== cfunToString;
|
|
592
581
|
if (reBuildC) {
|
|
593
582
|
model.colorTexture = vtkOpenGLTexture.newInstance({
|
|
@@ -605,7 +594,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
605
594
|
model.colorTexture.setMinificationFilter(Filter.LINEAR);
|
|
606
595
|
model.colorTexture.setMagnificationFilter(Filter.LINEAR);
|
|
607
596
|
}
|
|
608
|
-
if (
|
|
597
|
+
if (firstColorTransferFunc) {
|
|
609
598
|
const tmpTable = new Float32Array(cWidth * 3);
|
|
610
599
|
for (let c = 0; c < numIComps; c++) {
|
|
611
600
|
const cfun = actorProperty.getRGBTransferFunction(c);
|
|
@@ -632,13 +621,13 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
632
621
|
}
|
|
633
622
|
model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
634
623
|
}
|
|
635
|
-
if (
|
|
636
|
-
model._openGLRenderWindow.setGraphicsResourceForObject(
|
|
637
|
-
if (
|
|
638
|
-
model._openGLRenderWindow.registerGraphicsResourceUser(
|
|
624
|
+
if (firstColorTransferFunc) {
|
|
625
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(firstColorTransferFunc, model.colorTexture, cfunToString);
|
|
626
|
+
if (firstColorTransferFunc !== model._colorTransferFunc) {
|
|
627
|
+
model._openGLRenderWindow.registerGraphicsResourceUser(firstColorTransferFunc, publicAPI);
|
|
639
628
|
model._openGLRenderWindow.unregisterGraphicsResourceUser(model._colorTransferFunc, publicAPI);
|
|
640
629
|
}
|
|
641
|
-
model._colorTransferFunc =
|
|
630
|
+
model._colorTransferFunc = firstColorTransferFunc;
|
|
642
631
|
}
|
|
643
632
|
} else {
|
|
644
633
|
model.colorTexture = cTex.oglObject;
|
|
@@ -647,9 +636,13 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
647
636
|
// Build piecewise function buffer. This buffer is used either
|
|
648
637
|
// for component weighting or opacity, depending on whether we're
|
|
649
638
|
// rendering components independently or not.
|
|
650
|
-
const
|
|
651
|
-
|
|
652
|
-
|
|
639
|
+
const opacityFunctions = [];
|
|
640
|
+
for (let component = 0; component < numIComps; ++component) {
|
|
641
|
+
opacityFunctions.push(actorProperty.getPiecewiseFunction(component));
|
|
642
|
+
}
|
|
643
|
+
const pwfunToString = getTransferFunctionsHash(opacityFunctions, iComps, numIComps);
|
|
644
|
+
const firstPwFunc = actorProperty.getPiecewiseFunction();
|
|
645
|
+
const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(firstPwFunc);
|
|
653
646
|
// rebuild opacity tfun?
|
|
654
647
|
const reBuildPwf = !pwfTex?.oglObject?.getHandle() || pwfTex?.hash !== pwfunToString;
|
|
655
648
|
if (reBuildPwf) {
|
|
@@ -668,7 +661,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
668
661
|
model.pwfTexture.setMinificationFilter(Filter.LINEAR);
|
|
669
662
|
model.pwfTexture.setMagnificationFilter(Filter.LINEAR);
|
|
670
663
|
}
|
|
671
|
-
if (
|
|
664
|
+
if (firstPwFunc) {
|
|
672
665
|
const pwfFloatTable = new Float32Array(pwfSize);
|
|
673
666
|
const tmpTable = new Float32Array(pwfWidth);
|
|
674
667
|
for (let c = 0; c < numIComps; ++c) {
|
|
@@ -699,13 +692,13 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
699
692
|
pwfTable.fill(255.0);
|
|
700
693
|
model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable);
|
|
701
694
|
}
|
|
702
|
-
if (
|
|
703
|
-
model._openGLRenderWindow.setGraphicsResourceForObject(
|
|
704
|
-
if (
|
|
705
|
-
model._openGLRenderWindow.registerGraphicsResourceUser(
|
|
695
|
+
if (firstPwFunc) {
|
|
696
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(firstPwFunc, model.pwfTexture, pwfunToString);
|
|
697
|
+
if (firstPwFunc !== model._pwFunc) {
|
|
698
|
+
model._openGLRenderWindow.registerGraphicsResourceUser(firstPwFunc, publicAPI);
|
|
706
699
|
model._openGLRenderWindow.unregisterGraphicsResourceUser(model._pwFunc, publicAPI);
|
|
707
700
|
}
|
|
708
|
-
model._pwFunc =
|
|
701
|
+
model._pwFunc = firstPwFunc;
|
|
709
702
|
}
|
|
710
703
|
} else {
|
|
711
704
|
model.pwfTexture = pwfTex.oglObject;
|
|
@@ -903,7 +896,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
903
896
|
}
|
|
904
897
|
};
|
|
905
898
|
publicAPI.updatelabelOutlineThicknessTexture = image => {
|
|
906
|
-
const labelOutlineThicknessArray = image.getProperty().
|
|
899
|
+
const labelOutlineThicknessArray = image.getProperty().getLabelOutlineThickness();
|
|
907
900
|
const lTex = model._openGLRenderWindow.getGraphicsResourceForObject(labelOutlineThicknessArray);
|
|
908
901
|
|
|
909
902
|
// compute the join of the labelOutlineThicknessArray so that
|