@kitware/vtk.js 32.0.1 → 32.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.
@@ -285,7 +285,7 @@ function vtkOpenGLTexture(publicAPI, model) {
285
285
  publicAPI.getDefaultInternalFormat = (vtktype, numComps) => {
286
286
  let result = 0;
287
287
  // try default next
288
- result = model._openGLRenderWindow.getDefaultTextureInternalFormat(vtktype, numComps, model.oglNorm16Ext, model.useHalfFloat);
288
+ result = model._openGLRenderWindow.getDefaultTextureInternalFormat(vtktype, numComps, model.oglNorm16Ext, publicAPI.useHalfFloat());
289
289
  if (result) {
290
290
  return result;
291
291
  }
@@ -295,6 +295,7 @@ function vtkOpenGLTexture(publicAPI, model) {
295
295
  }
296
296
  return result;
297
297
  };
298
+ publicAPI.useHalfFloat = () => model.enableHalfFloat && model.canUseHalfFloat;
298
299
 
299
300
  //----------------------------------------------------------------------------
300
301
  publicAPI.setInternalFormat = iFormat => {
@@ -353,6 +354,7 @@ function vtkOpenGLTexture(publicAPI, model) {
353
354
 
354
355
  //----------------------------------------------------------------------------
355
356
  publicAPI.getDefaultDataType = vtkScalarType => {
357
+ const useHalfFloat = publicAPI.useHalfFloat();
356
358
  // DON'T DEAL with VTK_CHAR as this is platform dependent.
357
359
  if (model._openGLRenderWindow.getWebgl2()) {
358
360
  switch (vtkScalarType) {
@@ -362,14 +364,14 @@ function vtkOpenGLTexture(publicAPI, model) {
362
364
  return model.context.UNSIGNED_BYTE;
363
365
  // prefer norm16 since that is accurate compared to
364
366
  // half float which is not
365
- case model.oglNorm16Ext && !model.useHalfFloat && VtkDataTypes.SHORT:
367
+ case model.oglNorm16Ext && !useHalfFloat && VtkDataTypes.SHORT:
366
368
  return model.context.SHORT;
367
- case model.oglNorm16Ext && !model.useHalfFloat && VtkDataTypes.UNSIGNED_SHORT:
369
+ case model.oglNorm16Ext && !useHalfFloat && VtkDataTypes.UNSIGNED_SHORT:
368
370
  return model.context.UNSIGNED_SHORT;
369
371
  // use half float type
370
- case model.useHalfFloat && VtkDataTypes.SHORT:
372
+ case useHalfFloat && VtkDataTypes.SHORT:
371
373
  return model.context.HALF_FLOAT;
372
- case model.useHalfFloat && VtkDataTypes.UNSIGNED_SHORT:
374
+ case useHalfFloat && VtkDataTypes.UNSIGNED_SHORT:
373
375
  return model.context.HALF_FLOAT;
374
376
  // case VtkDataTypes.INT:
375
377
  // return model.context.INT;
@@ -490,8 +492,18 @@ function vtkOpenGLTexture(publicAPI, model) {
490
492
  }
491
493
  };
492
494
 
493
- //----------------------------------------------------------------------------
494
- function updateArrayDataType(dataType, data) {
495
+ /**
496
+ * Updates the data array to match the required data type for OpenGL.
497
+ *
498
+ * This function takes the input data and converts it to the appropriate
499
+ * format required by the OpenGL texture, based on the specified data type.
500
+ *
501
+ * @param {string} dataType - The original data type of the input data.
502
+ * @param {Array} data - The input data array that needs to be updated.
503
+ * @param {boolean} [depth=false] - Indicates whether the data is a 3D array.
504
+ * @returns {Array} The updated data array that matches the OpenGL data type.
505
+ */
506
+ publicAPI.updateArrayDataTypeForGL = function (dataType, data) {
495
507
  let depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
496
508
  const pixData = [];
497
509
  let pixCount = model.width * model.height * model.components;
@@ -556,7 +568,7 @@ function vtkOpenGLTexture(publicAPI, model) {
556
568
  }
557
569
  }
558
570
  return pixData;
559
- }
571
+ };
560
572
 
561
573
  //----------------------------------------------------------------------------
562
574
  function scaleTextureToHighestPowerOfTwo(data) {
@@ -683,7 +695,7 @@ function vtkOpenGLTexture(publicAPI, model) {
683
695
 
684
696
  // Create an array of texture with one texture
685
697
  const dataArray = [data];
686
- const pixData = updateArrayDataType(dataType, dataArray);
698
+ const pixData = publicAPI.updateArrayDataTypeForGL(dataType, dataArray);
687
699
  const scaledData = scaleTextureToHighestPowerOfTwo(pixData);
688
700
 
689
701
  // Source texture data from the PBO.
@@ -705,7 +717,7 @@ function vtkOpenGLTexture(publicAPI, model) {
705
717
  if (flip) {
706
718
  model.context.pixelStorei(model.context.UNPACK_FLIP_Y_WEBGL, false);
707
719
  }
708
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, model.useHalfFloat);
720
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, publicAPI.useHalfFloat());
709
721
  publicAPI.deactivate();
710
722
  return true;
711
723
  };
@@ -730,7 +742,7 @@ function vtkOpenGLTexture(publicAPI, model) {
730
742
  model.maxLevel = data.length / 6 - 1;
731
743
  publicAPI.createTexture();
732
744
  publicAPI.bind();
733
- const pixData = updateArrayDataType(dataType, data);
745
+ const pixData = publicAPI.updateArrayDataTypeForGL(dataType, data);
734
746
  const scaledData = scaleTextureToHighestPowerOfTwo(pixData);
735
747
 
736
748
  // invert the data because opengl is messed up with cube maps
@@ -783,7 +795,7 @@ function vtkOpenGLTexture(publicAPI, model) {
783
795
  h /= 2;
784
796
  }
785
797
  }
786
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, model.useHalfFloat);
798
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, publicAPI.useHalfFloat());
787
799
  // generateMipmap must not be called here because we manually upload all levels
788
800
  // if it is called, all levels will be overwritten
789
801
 
@@ -833,7 +845,7 @@ function vtkOpenGLTexture(publicAPI, model) {
833
845
  if (model.generateMipmap) {
834
846
  model.context.generateMipmap(model.target);
835
847
  }
836
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, model.useHalfFloat);
848
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, publicAPI.useHalfFloat());
837
849
  publicAPI.deactivate();
838
850
  return true;
839
851
  };
@@ -883,7 +895,7 @@ function vtkOpenGLTexture(publicAPI, model) {
883
895
  if (model.generateMipmap) {
884
896
  model.context.generateMipmap(model.target);
885
897
  }
886
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(VtkDataTypes.UNSIGNED_CHAR, model.oglNorm16Ext, model.useHalfFloat);
898
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(VtkDataTypes.UNSIGNED_CHAR, model.oglNorm16Ext, publicAPI.useHalfFloat());
887
899
  publicAPI.deactivate();
888
900
  return true;
889
901
  };
@@ -915,7 +927,7 @@ function vtkOpenGLTexture(publicAPI, model) {
915
927
  }
916
928
  return true;
917
929
  }
918
- function setUseHalfFloat(dataType, offset, scale, preferSizeOverAccuracy) {
930
+ function setCanUseHalfFloat(dataType, offset, scale, preferSizeOverAccuracy) {
919
931
  publicAPI.getOpenGLDataType(dataType);
920
932
  let useHalfFloat = false;
921
933
  if (model._openGLRenderWindow.getWebgl2()) {
@@ -928,7 +940,7 @@ function vtkOpenGLTexture(publicAPI, model) {
928
940
  // Don't consider halfFloat and convert back to Float when the range of data does not generate an accurate halfFloat
929
941
  // AND it is not preferable to have a smaller texture than an exact texture.
930
942
  const isHalfFloat = useHalfFloat && (hasExactHalfFloat(offset, scale) || preferSizeOverAccuracy);
931
- model.useHalfFloat = isHalfFloat;
943
+ model.canUseHalfFloat = isHalfFloat;
932
944
  }
933
945
  function processDataArray(dataArray, preferSizeOverAccuracy) {
934
946
  const numComps = dataArray.getNumberOfComponents();
@@ -948,11 +960,11 @@ function vtkOpenGLTexture(publicAPI, model) {
948
960
 
949
961
  // preferSizeOverAccuracy will override norm16 due to bug with norm16 implementation
950
962
  // https://bugs.chromium.org/p/chromium/issues/detail?id=1408247
951
- setUseHalfFloat(dataType, scaleOffsets.offset, scaleOffsets.scale, preferSizeOverAccuracy);
963
+ setCanUseHalfFloat(dataType, scaleOffsets.offset, scaleOffsets.scale, preferSizeOverAccuracy);
952
964
 
953
965
  // since our default is to use half float, in case that we can't use it
954
966
  // we need to use another type
955
- if (!model.useHalfFloat) {
967
+ if (!publicAPI.useHalfFloat()) {
956
968
  publicAPI.getOpenGLDataType(dataType, true);
957
969
  }
958
970
  return {
@@ -979,14 +991,88 @@ function vtkOpenGLTexture(publicAPI, model) {
979
991
  } = processDataArray(dataArray, preferSizeOverAccuracy);
980
992
  publicAPI.create2DFromRaw(width, height, numComps, dataType, data);
981
993
  };
994
+ publicAPI.updateVolumeInfoForGL = (dataType, numComps) => {
995
+ let isScalingApplied = false;
996
+ const useHalfFloat = publicAPI.useHalfFloat();
997
+
998
+ // Initialize volume info if it doesn't exist
999
+ if (!model.volumeInfo?.scale || !model.volumeInfo?.offset) {
1000
+ model.volumeInfo = {
1001
+ scale: new Array(numComps),
1002
+ offset: new Array(numComps)
1003
+ };
1004
+ }
1005
+
1006
+ // Default scaling and offset
1007
+ for (let c = 0; c < numComps; ++c) {
1008
+ model.volumeInfo.scale[c] = 1.0;
1009
+ model.volumeInfo.offset[c] = 0.0;
1010
+ }
1011
+
1012
+ // Handle SHORT data type with EXT_texture_norm16 extension
1013
+ if (model.oglNorm16Ext && !useHalfFloat && dataType === VtkDataTypes.SHORT) {
1014
+ for (let c = 0; c < numComps; ++c) {
1015
+ model.volumeInfo.scale[c] = 32767.0; // Scale to [-1, 1] range
1016
+ }
1017
+
1018
+ isScalingApplied = true;
1019
+ }
1020
+
1021
+ // Handle UNSIGNED_SHORT data type with EXT_texture_norm16 extension
1022
+ if (model.oglNorm16Ext && !useHalfFloat && dataType === VtkDataTypes.UNSIGNED_SHORT) {
1023
+ for (let c = 0; c < numComps; ++c) {
1024
+ model.volumeInfo.scale[c] = 65535.0; // Scale to [0, 1] range
1025
+ }
1026
+
1027
+ isScalingApplied = true;
1028
+ }
1029
+
1030
+ // Handle UNSIGNED_CHAR data type
1031
+ if (dataType === VtkDataTypes.UNSIGNED_CHAR) {
1032
+ for (let c = 0; c < numComps; ++c) {
1033
+ model.volumeInfo.scale[c] = 255.0; // Scale to [0, 1] range
1034
+ }
1035
+
1036
+ isScalingApplied = true;
1037
+ }
1038
+
1039
+ // No scaling needed for FLOAT or HalfFloat (SHORT/UNSIGNED_SHORT)
1040
+ if (dataType === VtkDataTypes.FLOAT || useHalfFloat && (dataType === VtkDataTypes.SHORT || dataType === VtkDataTypes.UNSIGNED_SHORT)) {
1041
+ isScalingApplied = true;
1042
+ }
1043
+ return isScalingApplied;
1044
+ };
1045
+
982
1046
  //----------------------------------------------------------------------------
983
1047
  publicAPI.create3DFromRaw = (width, height, depth, numComps, dataType, data) => {
1048
+ let dataTypeToUse = dataType;
1049
+ let dataToUse = data;
1050
+ if (!publicAPI.updateVolumeInfoForGL(dataTypeToUse, numComps) && dataToUse) {
1051
+ const numPixelsIn = width * height * depth;
1052
+ const scaleOffsetsCopy = structuredClone(model.volumeInfo);
1053
+ // otherwise convert to float
1054
+ const newArray = new Float32Array(numPixelsIn * numComps);
1055
+ // use computed scale and offset
1056
+ model.volumeInfo.offset = scaleOffsetsCopy.offset;
1057
+ model.volumeInfo.scale = scaleOffsetsCopy.scale;
1058
+ let count = 0;
1059
+ const scaleInverse = scaleOffsetsCopy.scale.map(s => 1 / s);
1060
+ for (let i = 0; i < numPixelsIn; i++) {
1061
+ for (let nc = 0; nc < numComps; nc++) {
1062
+ newArray[count] = (dataToUse[count] - scaleOffsetsCopy.offset[nc]) * scaleInverse[nc];
1063
+ count++;
1064
+ }
1065
+ }
1066
+ dataTypeToUse = VtkDataTypes.FLOAT;
1067
+ dataToUse = newArray;
1068
+ }
1069
+
984
1070
  // Permit OpenGLDataType to be half float, if applicable, for 3D
985
- publicAPI.getOpenGLDataType(dataType);
1071
+ publicAPI.getOpenGLDataType(dataTypeToUse);
986
1072
 
987
1073
  // Now determine the texture parameters using the arguments.
988
- publicAPI.getInternalFormat(dataType, numComps);
989
- publicAPI.getFormat(dataType, numComps);
1074
+ publicAPI.getInternalFormat(dataTypeToUse, numComps);
1075
+ publicAPI.getFormat(dataTypeToUse, numComps);
990
1076
  if (!model.internalFormat || !model.format || !model.openGLDataType) {
991
1077
  vtkErrorMacro('Failed to determine texture parameters.');
992
1078
  return false;
@@ -1001,9 +1087,9 @@ function vtkOpenGLTexture(publicAPI, model) {
1001
1087
  publicAPI.createTexture();
1002
1088
  publicAPI.bind();
1003
1089
  // Create an array of texture with one texture
1004
- const dataArray = [data];
1090
+ const dataArray = [dataToUse];
1005
1091
  const is3DArray = true;
1006
- const pixData = updateArrayDataType(dataType, dataArray, is3DArray);
1092
+ const pixData = publicAPI.updateArrayDataTypeForGL(dataTypeToUse, dataArray, is3DArray);
1007
1093
  const scaledData = scaleTextureToHighestPowerOfTwo(pixData);
1008
1094
 
1009
1095
  // Source texture data from the PBO.
@@ -1012,7 +1098,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1012
1098
 
1013
1099
  // openGLDataType
1014
1100
 
1015
- if (useTexStorage(dataType)) {
1101
+ if (useTexStorage(dataTypeToUse)) {
1016
1102
  model.context.texStorage3D(model.target, 1, model.internalFormat, model.width, model.height, model.depth);
1017
1103
  if (scaledData[0] != null) {
1018
1104
  model.context.texSubImage3D(model.target, 0, 0, 0, 0, model.width, model.height, model.depth, model.format, model.openGLDataType, scaledData[0]);
@@ -1023,7 +1109,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1023
1109
  if (model.generateMipmap) {
1024
1110
  model.context.generateMipmap(model.target);
1025
1111
  }
1026
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, model.useHalfFloat);
1112
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataTypeToUse, model.oglNorm16Ext, publicAPI.useHalfFloat());
1027
1113
  publicAPI.deactivate();
1028
1114
  return true;
1029
1115
  };
@@ -1050,7 +1136,6 @@ function vtkOpenGLTexture(publicAPI, model) {
1050
1136
  data,
1051
1137
  scaleOffsets
1052
1138
  } = processDataArray(dataArray, preferSizeOverAccuracy);
1053
- const numPixelsIn = width * height * depth;
1054
1139
  const offset = [];
1055
1140
  const scale = [];
1056
1141
  for (let c = 0; c < numComps; ++c) {
@@ -1076,46 +1161,13 @@ function vtkOpenGLTexture(publicAPI, model) {
1076
1161
  // Create a copy of scale and offset to avoid aliasing issues
1077
1162
  // Original is read only, copy is read/write
1078
1163
  // Use the copy as volumeInfo.scale and volumeInfo.offset
1079
- const scaleOffsetsCopy = structuredClone(scaleOffsets);
1080
1164
 
1081
1165
  // WebGL2 path, we have 3d textures etc
1082
1166
  if (model._openGLRenderWindow.getWebgl2()) {
1083
- if (model.oglNorm16Ext && !model.useHalfFloat && dataType === VtkDataTypes.SHORT) {
1084
- for (let c = 0; c < numComps; ++c) {
1085
- model.volumeInfo.scale[c] = 32767.0;
1086
- }
1087
- return publicAPI.create3DFromRaw(width, height, depth, numComps, dataType, data);
1088
- }
1089
- if (model.oglNorm16Ext && !model.useHalfFloat && dataType === VtkDataTypes.UNSIGNED_SHORT) {
1090
- for (let c = 0; c < numComps; ++c) {
1091
- model.volumeInfo.scale[c] = 65535.0;
1092
- }
1093
- return publicAPI.create3DFromRaw(width, height, depth, numComps, dataType, data);
1094
- }
1095
- if (dataType === VtkDataTypes.FLOAT || model.useHalfFloat && (dataType === VtkDataTypes.SHORT || dataType === VtkDataTypes.UNSIGNED_SHORT)) {
1096
- return publicAPI.create3DFromRaw(width, height, depth, numComps, dataType, data);
1097
- }
1098
- if (dataType === VtkDataTypes.UNSIGNED_CHAR) {
1099
- for (let c = 0; c < numComps; ++c) {
1100
- model.volumeInfo.scale[c] = 255.0;
1101
- }
1102
- return publicAPI.create3DFromRaw(width, height, depth, numComps, dataType, data);
1103
- }
1104
- // otherwise convert to float
1105
- const newArray = new Float32Array(numPixelsIn * numComps);
1106
- // use computed scale and offset
1107
- model.volumeInfo.offset = scaleOffsetsCopy.offset;
1108
- model.volumeInfo.scale = scaleOffsetsCopy.scale;
1109
- let count = 0;
1110
- const scaleInverse = scaleOffsetsCopy.scale.map(s => 1 / s);
1111
- for (let i = 0; i < numPixelsIn; i++) {
1112
- for (let nc = 0; nc < numComps; nc++) {
1113
- newArray[count] = (data[count] - scaleOffsetsCopy.offset[nc]) * scaleInverse[nc];
1114
- count++;
1115
- }
1116
- }
1117
- return publicAPI.create3DFromRaw(width, height, depth, numComps, VtkDataTypes.FLOAT, newArray);
1167
+ return publicAPI.create3DFromRaw(width, height, depth, numComps, dataType, data);
1118
1168
  }
1169
+ const numPixelsIn = width * height * depth;
1170
+ const scaleOffsetsCopy = structuredClone(scaleOffsets);
1119
1171
 
1120
1172
  // not webgl2, deal with webgl1, no 3d textures
1121
1173
  // and maybe no float textures
@@ -1267,6 +1319,11 @@ function vtkOpenGLTexture(publicAPI, model) {
1267
1319
  }
1268
1320
  return -1;
1269
1321
  };
1322
+
1323
+ // set use half float
1324
+ publicAPI.enableUseHalfFloat = use => {
1325
+ model.enableUseHalfFloat = use;
1326
+ };
1270
1327
  }
1271
1328
 
1272
1329
  // ----------------------------------------------------------------------------
@@ -1299,13 +1356,12 @@ const DEFAULT_VALUES = {
1299
1356
  baseLevel: 0,
1300
1357
  maxLevel: 1000,
1301
1358
  generateMipmap: false,
1302
- // use half float by default, but it will get set
1303
- // to false if the context does not support it or
1304
- // the voxel intensity range is out of the accurate
1305
- // range of half float
1306
- useHalfFloat: true,
1307
1359
  oglNorm16Ext: null,
1308
- allocatedGPUMemoryInBytes: 0
1360
+ allocatedGPUMemoryInBytes: 0,
1361
+ // by default it is enabled
1362
+ enableUseHalfFloat: true,
1363
+ // but by default we don't know if we can use half float base on the data range
1364
+ canUseHalfFloat: false
1309
1365
  };
1310
1366
 
1311
1367
  // ----------------------------------------------------------------------------
@@ -15,6 +15,7 @@ import { Representation } from '../Core/Property/Constants.js';
15
15
  import { Wrap, Filter } from './Texture/Constants.js';
16
16
  import { InterpolationType, OpacityMode, ColorMixPreset } from '../Core/VolumeProperty/Constants.js';
17
17
  import { BlendMode } from '../Core/VolumeMapper/Constants.js';
18
+ import { getTransferFunctionHash, getImageDataHash } from './RenderWindow/resourceSharingHelper.js';
18
19
  import { v as vtkVolumeVS } from './glsl/vtkVolumeVS.glsl.js';
19
20
  import { v as vtkVolumeFS } from './glsl/vtkVolumeFS.glsl.js';
20
21
  import { registerOverride } from './ViewNodeFactory.js';
@@ -28,9 +29,6 @@ const {
28
29
  // helper methods
29
30
  // ----------------------------------------------------------------------------
30
31
 
31
- function computeFnToString(pwfun, useIComps, numberOfComponents) {
32
- return pwfun ? `${pwfun.getMTime()}-${useIComps}-${numberOfComponents}` : '0';
33
- }
34
32
  function getColorCodeFromPreset(colorMixPreset) {
35
33
  switch (colorMixPreset) {
36
34
  case ColorMixPreset.CUSTOM:
@@ -417,18 +415,23 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
417
415
  program.setUniformf('sampleDistance', publicAPI.getCurrentSampleDistance(ren));
418
416
  const volInfo = model.scalarTexture.getVolumeInfo();
419
417
  const ipScalarRange = model.renderable.getIpScalarRange();
420
- const minVals = [];
421
- const maxVals = [];
422
- for (let i = 0; i < 4; i++) {
423
- // convert iprange from 0-1 into data range values
424
- minVals[i] = ipScalarRange[0] * volInfo.dataComputedScale[i] + volInfo.dataComputedOffset[i];
425
- maxVals[i] = ipScalarRange[1] * volInfo.dataComputedScale[i] + volInfo.dataComputedOffset[i];
426
- // convert data ranges into texture values
427
- minVals[i] = (minVals[i] - volInfo.offset[i]) / volInfo.scale[i];
428
- maxVals[i] = (maxVals[i] - volInfo.offset[i]) / volInfo.scale[i];
429
- }
430
- program.setUniform4f('ipScalarRangeMin', minVals[0], minVals[1], minVals[2], minVals[3]);
431
- program.setUniform4f('ipScalarRangeMax', maxVals[0], maxVals[1], maxVals[2], maxVals[3]);
418
+
419
+ // In some situations, we might not have computed the scale and offset
420
+ // for the data range, or it might not be needed.
421
+ if (volInfo?.dataComputedScale?.length) {
422
+ const minVals = [];
423
+ const maxVals = [];
424
+ for (let i = 0; i < 4; i++) {
425
+ // convert iprange from 0-1 into data range values
426
+ minVals[i] = ipScalarRange[0] * volInfo.dataComputedScale[i] + volInfo.dataComputedOffset[i];
427
+ maxVals[i] = ipScalarRange[1] * volInfo.dataComputedScale[i] + volInfo.dataComputedOffset[i];
428
+ // convert data ranges into texture values
429
+ minVals[i] = (minVals[i] - volInfo.offset[i]) / volInfo.scale[i];
430
+ maxVals[i] = (maxVals[i] - volInfo.offset[i]) / volInfo.scale[i];
431
+ }
432
+ program.setUniform4f('ipScalarRangeMin', minVals[0], minVals[1], minVals[2], minVals[3]);
433
+ program.setUniform4f('ipScalarRangeMax', maxVals[0], maxVals[1], maxVals[2], maxVals[3]);
434
+ }
432
435
 
433
436
  // if we have a zbuffer texture then set it
434
437
  if (model.zBufferTexture !== null) {
@@ -1044,7 +1047,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1044
1047
  const numIComps = useIndependentComps ? numComp : 1;
1045
1048
  const scalarOpacityFunc = vprop.getScalarOpacity();
1046
1049
  const opTex = model._openGLRenderWindow.getGraphicsResourceForObject(scalarOpacityFunc);
1047
- let toString = computeFnToString(scalarOpacityFunc, useIndependentComps, numIComps);
1050
+ let toString = getTransferFunctionHash(scalarOpacityFunc, useIndependentComps, numIComps);
1048
1051
  const reBuildOp = !opTex?.oglObject || opTex.hash !== toString;
1049
1052
  if (reBuildOp) {
1050
1053
  model.opacityTexture = vtkOpenGLTexture.newInstance();
@@ -1096,7 +1099,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1096
1099
 
1097
1100
  // rebuild color tfun?
1098
1101
  const colorTransferFunc = vprop.getRGBTransferFunction();
1099
- toString = computeFnToString(colorTransferFunc, useIndependentComps, numIComps);
1102
+ toString = getTransferFunctionHash(colorTransferFunc, useIndependentComps, numIComps);
1100
1103
  const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
1101
1104
  const reBuildC = !cTex?.oglObject?.getHandle() || cTex?.hash !== toString;
1102
1105
  if (reBuildC) {
@@ -1133,7 +1136,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1133
1136
  publicAPI.updateLabelOutlineThicknessTexture(actor);
1134
1137
  const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
1135
1138
  // rebuild the scalarTexture if the data has changed
1136
- toString = `${image.getMTime()}A${scalars.getMTime()}`;
1139
+ toString = getImageDataHash(image, scalars);
1137
1140
  const reBuildTex = !tex?.oglObject?.getHandle() || tex?.hash !== toString;
1138
1141
  if (reBuildTex) {
1139
1142
  model.scalarTexture = vtkOpenGLTexture.newInstance();
package/index.d.ts CHANGED
@@ -31,6 +31,7 @@
31
31
  /// <reference path="./Common/DataModel/EdgeLocator.d.ts" />
32
32
  /// <reference path="./Common/DataModel/ITKHelper.d.ts" />
33
33
  /// <reference path="./Common/DataModel/ImageData.d.ts" />
34
+ /// <reference path="./Common/DataModel/ImplicitFunction.d.ts" />
34
35
  /// <reference path="./Common/DataModel/IncrementalOctreeNode.d.ts" />
35
36
  /// <reference path="./Common/DataModel/IncrementalOctreePointLocator.d.ts" />
36
37
  /// <reference path="./Common/DataModel/KochanekSpline1D.d.ts" />
@@ -216,6 +217,7 @@
216
217
  /// <reference path="./Rendering/OpenGL/HardwareSelector/Constants.d.ts" />
217
218
  /// <reference path="./Rendering/OpenGL/HardwareSelector.d.ts" />
218
219
  /// <reference path="./Rendering/OpenGL/RenderWindow.d.ts" />
220
+ /// <reference path="./Rendering/OpenGL/RenderWindow/resourceSharingHelper.d.ts" />
219
221
  /// <reference path="./Rendering/OpenGL/Texture/Constants.d.ts" />
220
222
  /// <reference path="./Rendering/OpenGL/Texture.d.ts" />
221
223
  /// <reference path="./Rendering/SceneGraph/RenderPass.d.ts" />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitware/vtk.js",
3
- "version": "32.0.1",
3
+ "version": "32.1.0",
4
4
  "description": "Visualization Toolkit for the Web",
5
5
  "keywords": [
6
6
  "3d",