@kitware/vtk.js 30.9.3 → 31.0.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.
@@ -104,17 +104,18 @@ function vtkFullScreenRenderWindow(publicAPI, model) {
104
104
  publicAPI.toggleControllerVisibility = () => {
105
105
  publicAPI.setControllerVisibility(!model.controllerVisibility);
106
106
  };
107
+ function handleKeypress(e) {
108
+ if (String.fromCharCode(e.charCode) === 'c') {
109
+ publicAPI.toggleControllerVisibility();
110
+ }
111
+ }
107
112
  publicAPI.addController = html => {
108
113
  model.controlContainer = document.createElement('div');
109
114
  applyStyle(model.controlContainer, model.controlPanelStyle || STYLE_CONTROL_PANEL);
110
115
  model.rootContainer.appendChild(model.controlContainer);
111
116
  model.controlContainer.innerHTML = html;
112
117
  publicAPI.setControllerVisibility(model.controllerVisibility);
113
- model.rootContainer.addEventListener('keypress', e => {
114
- if (String.fromCharCode(e.charCode) === 'c') {
115
- publicAPI.toggleControllerVisibility();
116
- }
117
- });
118
+ model.rootContainer.addEventListener('keypress', handleKeypress);
118
119
  };
119
120
 
120
121
  // Update BG color
@@ -131,7 +132,10 @@ function vtkFullScreenRenderWindow(publicAPI, model) {
131
132
  };
132
133
 
133
134
  // Properly release GL context
134
- publicAPI.delete = macro.chain(publicAPI.setContainer, model.apiSpecificRenderWindow.delete, publicAPI.delete);
135
+ publicAPI.delete = macro.chain(publicAPI.setContainer, model.apiSpecificRenderWindow.delete, () => {
136
+ model.rootContainer?.removeEventListener('keypress', handleKeypress);
137
+ window.removeEventListener('resize', publicAPI.resize);
138
+ }, publicAPI.delete);
135
139
 
136
140
  // Handle window resize
137
141
  publicAPI.resize = () => {
@@ -68,7 +68,9 @@ function vtkGenericRenderWindow(publicAPI, model) {
68
68
  };
69
69
 
70
70
  // Properly release GL context
71
- publicAPI.delete = macro.chain(publicAPI.setContainer, model._apiSpecificRenderWindow.delete, publicAPI.delete);
71
+ publicAPI.delete = macro.chain(publicAPI.setContainer, model._apiSpecificRenderWindow.delete, () => {
72
+ window.removeEventListener('resize', publicAPI.resize);
73
+ }, publicAPI.delete);
72
74
 
73
75
  // Handle size
74
76
  if (model.listenWindowResize) {
@@ -113,7 +113,7 @@ function vtkOpenGLActor(publicAPI, model) {
113
113
  // Renders myself
114
114
  publicAPI.translucentPass = (prepass, renderPass) => {
115
115
  if (prepass) {
116
- model.context.depthMask(false);
116
+ model.context.depthMask(model._openGLRenderer.getSelector() && model.renderable.getNestedPickable());
117
117
  publicAPI.activateTextures();
118
118
  } else if (model.activeTextures) {
119
119
  for (let index = 0; index < model.activeTextures.length; index++) {
@@ -1,6 +1,6 @@
1
1
  import { mat4, mat3 } from 'gl-matrix';
2
2
  import Constants from '../Core/ImageMapper/Constants.js';
3
- import { n as newInstance$1, e as setGet, o as obj, r as vtkErrorMacro$1, c as macro } from '../../macros2.js';
3
+ import { n as newInstance$1, e as setGet, o as obj, r as vtkErrorMacro$1, h as chain, c as macro } from '../../macros2.js';
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';
@@ -55,12 +55,23 @@ function splitStringOnEnter(inputString) {
55
55
  function vtkOpenGLImageMapper(publicAPI, model) {
56
56
  // Set our className
57
57
  model.classHierarchy.push('vtkOpenGLImageMapper');
58
+ function unregisterGraphicsResources(renderWindow) {
59
+ // The openGLTexture is not shared
60
+ model.openGLTexture.releaseGraphicsResources(renderWindow);
61
+ // All these other resources are shared
62
+ [model._colorTransferFunc, model._pwFunc, model._labelOutlineThicknessArray].forEach(coreObject => renderWindow.unregisterGraphicsResourceUser(coreObject, publicAPI));
63
+ }
58
64
  publicAPI.buildPass = prepass => {
59
65
  if (prepass) {
60
66
  model.currentRenderPass = null;
61
67
  model.openGLImageSlice = publicAPI.getFirstAncestorOfType('vtkOpenGLImageSlice');
62
68
  model._openGLRenderer = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderer');
69
+ const oldOglRenderWindow = model._openGLRenderWindow;
63
70
  model._openGLRenderWindow = model._openGLRenderer.getLastAncestorOfType('vtkOpenGLRenderWindow');
71
+ if (oldOglRenderWindow && !oldOglRenderWindow.isDeleted() && oldOglRenderWindow !== model._openGLRenderWindow) {
72
+ // Unregister the mapper when the render window changes
73
+ unregisterGraphicsResources(oldOglRenderWindow);
74
+ }
64
75
  model.context = model._openGLRenderWindow.getContext();
65
76
  model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
66
77
  const ren = model._openGLRenderer.getRenderable();
@@ -571,17 +582,15 @@ function vtkOpenGLImageMapper(publicAPI, model) {
571
582
  const colorTransferFunc = actorProperty.getRGBTransferFunction();
572
583
  const cfunToString = computeFnToString(actorProperty, colorTransferFunc, numIComps);
573
584
  const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
574
- const reBuildC = !cTex?.vtkObj?.getHandle() || cTex?.hash !== cfunToString || model.colorTextureString !== cfunToString;
585
+ const reBuildC = !cTex?.oglObject?.getHandle() || cTex?.hash !== cfunToString;
575
586
  if (reBuildC) {
587
+ model.colorTexture = vtkOpenGLTexture.newInstance({
588
+ resizable: true
589
+ });
590
+ model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
576
591
  const cWidth = 1024;
577
592
  const cSize = cWidth * textureHeight * 3;
578
593
  const cTable = new Uint8ClampedArray(cSize);
579
- if (!model.colorTexture) {
580
- model.colorTexture = vtkOpenGLTexture.newInstance({
581
- resizable: true
582
- });
583
- model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
584
- }
585
594
  // set interpolation on the texture based on property setting
586
595
  if (iType === InterpolationType.NEAREST) {
587
596
  model.colorTexture.setMinificationFilter(Filter.NEAREST);
@@ -607,7 +616,6 @@ function vtkOpenGLImageMapper(publicAPI, model) {
607
616
  }
608
617
  }
609
618
  }
610
- model.colorTexture.releaseGraphicsResources(model._openGLRenderWindow);
611
619
  model.colorTexture.resetFormatAndType();
612
620
  model.colorTexture.create2DFromRaw(cWidth, textureHeight, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
613
621
  } else {
@@ -618,13 +626,16 @@ function vtkOpenGLImageMapper(publicAPI, model) {
618
626
  }
619
627
  model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
620
628
  }
621
- model.colorTextureString = cfunToString;
622
629
  if (colorTransferFunc) {
623
- model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, model.colorTextureString);
630
+ model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, cfunToString);
631
+ if (colorTransferFunc !== model._colorTransferFunc) {
632
+ model._openGLRenderWindow.registerGraphicsResourceUser(colorTransferFunc, publicAPI);
633
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._colorTransferFunc, publicAPI);
634
+ }
635
+ model._colorTransferFunc = colorTransferFunc;
624
636
  }
625
637
  } else {
626
- model.colorTexture = cTex.vtkObj;
627
- model.colorTextureString = cTex.hash;
638
+ model.colorTexture = cTex.oglObject;
628
639
  }
629
640
 
630
641
  // Build piecewise function buffer. This buffer is used either
@@ -634,17 +645,15 @@ function vtkOpenGLImageMapper(publicAPI, model) {
634
645
  const pwfunToString = computeFnToString(actorProperty, pwFunc, numIComps);
635
646
  const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
636
647
  // rebuild opacity tfun?
637
- const reBuildPwf = !pwfTex?.vtkObj?.getHandle() || pwfTex?.hash !== pwfunToString || model.pwfTextureString !== pwfunToString;
648
+ const reBuildPwf = !pwfTex?.oglObject?.getHandle() || pwfTex?.hash !== pwfunToString;
638
649
  if (reBuildPwf) {
639
650
  const pwfWidth = 1024;
640
651
  const pwfSize = pwfWidth * textureHeight;
641
652
  const pwfTable = new Uint8ClampedArray(pwfSize);
642
- if (!model.pwfTexture) {
643
- model.pwfTexture = vtkOpenGLTexture.newInstance({
644
- resizable: true
645
- });
646
- model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
647
- }
653
+ model.pwfTexture = vtkOpenGLTexture.newInstance({
654
+ resizable: true
655
+ });
656
+ model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
648
657
  // set interpolation on the texture based on property setting
649
658
  if (iType === InterpolationType.NEAREST) {
650
659
  model.pwfTexture.setMinificationFilter(Filter.NEAREST);
@@ -677,7 +686,6 @@ function vtkOpenGLImageMapper(publicAPI, model) {
677
686
  }
678
687
  }
679
688
  }
680
- model.pwfTexture.releaseGraphicsResources(model._openGLRenderWindow);
681
689
  model.pwfTexture.resetFormatAndType();
682
690
  model.pwfTexture.create2DFromRaw(pwfWidth, textureHeight, 1, VtkDataTypes.FLOAT, pwfFloatTable);
683
691
  } else {
@@ -685,13 +693,16 @@ function vtkOpenGLImageMapper(publicAPI, model) {
685
693
  pwfTable.fill(255.0);
686
694
  model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable);
687
695
  }
688
- model.pwfTextureString = pwfunToString;
689
696
  if (pwFunc) {
690
- model._openGLRenderWindow.setGraphicsResourceForObject(pwFunc, model.pwfTexture, model.pwfTextureString);
697
+ model._openGLRenderWindow.setGraphicsResourceForObject(pwFunc, model.pwfTexture, pwfunToString);
698
+ if (pwFunc !== model._pwFunc) {
699
+ model._openGLRenderWindow.registerGraphicsResourceUser(pwFunc, publicAPI);
700
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._pwFunc, publicAPI);
701
+ }
702
+ model._pwFunc = pwFunc;
691
703
  }
692
704
  } else {
693
- model.pwfTexture = pwfTex.vtkObj;
694
- model.pwfTextureString = pwfTex.hash;
705
+ model.pwfTexture = pwfTex.oglObject;
695
706
  }
696
707
 
697
708
  // Build outline thickness buffer
@@ -736,8 +747,8 @@ function vtkOpenGLImageMapper(publicAPI, model) {
736
747
  model.openGLTexture = vtkOpenGLTexture.newInstance({
737
748
  resizable: true
738
749
  });
739
- model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
740
750
  }
751
+ model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
741
752
  // Use norm16 for scalar texture if the extension is available
742
753
  model.openGLTexture.setOglNorm16Ext(model.context.getExtension('EXT_texture_norm16'));
743
754
  if (iType === InterpolationType.NEAREST) {
@@ -845,19 +856,11 @@ function vtkOpenGLImageMapper(publicAPI, model) {
845
856
  } else {
846
857
  vtkErrorMacro('Reformat slicing not yet supported.');
847
858
  }
848
- const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
849
- if (!tex?.vtkObj?.getHandle()) {
850
- if (model._scalars !== scalars) {
851
- model._openGLRenderWindow.releaseGraphicsResourcesForObject(model._scalars);
852
- model._scalars = scalars;
853
- }
854
- model.openGLTexture.resetFormatAndType();
855
- model.openGLTexture.create2DFilterableFromRaw(dims[0], dims[1], numComp, imgScalars.getDataType(), scalars, model.renderable.getPreferSizeOverAccuracy?.());
856
- model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.openGLTexture, model.VBOBuildString);
857
- } else {
858
- model.openGLTexture = tex.vtkObj;
859
- model.VBOBuildString = tex.hash;
860
- }
859
+
860
+ // Don't share this resource as `scalars` is created in this function
861
+ // so it is impossible to share
862
+ model.openGLTexture.resetFormatAndType();
863
+ model.openGLTexture.create2DFilterableFromRaw(dims[0], dims[1], numComp, imgScalars.getDataType(), scalars, model.renderable.getPreferSizeOverAccuracy?.());
861
864
  model.openGLTexture.activate();
862
865
  model.openGLTexture.sendParameters();
863
866
  model.openGLTexture.deactivate();
@@ -894,12 +897,6 @@ function vtkOpenGLImageMapper(publicAPI, model) {
894
897
  }
895
898
  };
896
899
  publicAPI.updatelabelOutlineThicknessTexture = image => {
897
- if (!model.labelOutlineThicknessTexture) {
898
- model.labelOutlineThicknessTexture = vtkOpenGLTexture.newInstance({
899
- resizable: false
900
- });
901
- model.labelOutlineThicknessTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
902
- }
903
900
  const labelOutlineThicknessArray = image.getProperty().getLabelOutlineThickness();
904
901
  const lTex = model._openGLRenderWindow.getGraphicsResourceForObject(labelOutlineThicknessArray);
905
902
 
@@ -907,7 +904,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
907
904
  // we can use it to decide whether to rebuild the labelOutlineThicknessTexture
908
905
  // or not
909
906
  const toString = `${labelOutlineThicknessArray.join('-')}`;
910
- const reBuildL = !lTex?.vtkObj?.getHandle() || lTex?.hash !== toString || model.labelOutlineThicknessTextureString !== toString;
907
+ const reBuildL = !lTex?.oglObject?.getHandle() || lTex?.hash !== toString;
911
908
  if (reBuildL) {
912
909
  const lWidth = 1024;
913
910
  const lHeight = 1;
@@ -921,20 +918,26 @@ function vtkOpenGLImageMapper(publicAPI, model) {
921
918
  const thickness = typeof labelOutlineThicknessArray[i] !== 'undefined' ? labelOutlineThicknessArray[i] : labelOutlineThicknessArray[0];
922
919
  lTable[i] = thickness;
923
920
  }
924
- model.labelOutlineThicknessTexture.releaseGraphicsResources(model._openGLRenderWindow);
921
+ model.labelOutlineThicknessTexture = vtkOpenGLTexture.newInstance({
922
+ resizable: false
923
+ });
924
+ model.labelOutlineThicknessTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
925
925
  model.labelOutlineThicknessTexture.resetFormatAndType();
926
926
  model.labelOutlineThicknessTexture.setMinificationFilter(Filter.NEAREST);
927
927
  model.labelOutlineThicknessTexture.setMagnificationFilter(Filter.NEAREST);
928
928
 
929
929
  // Create a 2D texture (acting as 1D) from the raw data
930
930
  model.labelOutlineThicknessTexture.create2DFromRaw(lWidth, lHeight, 1, VtkDataTypes.UNSIGNED_CHAR, lTable);
931
- model.labelOutlineThicknessTextureString = toString;
932
931
  if (labelOutlineThicknessArray) {
933
- model._openGLRenderWindow.setGraphicsResourceForObject(labelOutlineThicknessArray, model.labelOutlineThicknessTexture, model.labelOutlineThicknessTextureString);
932
+ model._openGLRenderWindow.setGraphicsResourceForObject(labelOutlineThicknessArray, model.labelOutlineThicknessTexture, toString);
933
+ if (labelOutlineThicknessArray !== model._labelOutlineThicknessArray) {
934
+ model._openGLRenderWindow.registerGraphicsResourceUser(labelOutlineThicknessArray, publicAPI);
935
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._labelOutlineThicknessArray, publicAPI);
936
+ }
937
+ model._labelOutlineThicknessArray = labelOutlineThicknessArray;
934
938
  }
935
939
  } else {
936
- model.labelOutlineThicknessTexture = lTex.vtkObj;
937
- model.labelOutlineThicknessTextureString = lTex.hash;
940
+ model.labelOutlineThicknessTexture = lTex.oglObject;
938
941
  }
939
942
  };
940
943
  publicAPI.getRenderTargetSize = () => {
@@ -954,6 +957,11 @@ function vtkOpenGLImageMapper(publicAPI, model) {
954
957
  } = model._openGLRenderer.getTiledSizeAndOrigin();
955
958
  return [lowerLeftU, lowerLeftV];
956
959
  };
960
+ publicAPI.delete = chain(() => {
961
+ if (model._openGLRenderWindow) {
962
+ unregisterGraphicsResources(model._openGLRenderWindow);
963
+ }
964
+ }, publicAPI.delete);
957
965
  }
958
966
 
959
967
  // ----------------------------------------------------------------------------
@@ -973,8 +981,11 @@ const DEFAULT_VALUES = {
973
981
  labelOutlineThicknessTextureString: null,
974
982
  lastHaveSeenDepthRequest: false,
975
983
  haveSeenDepthRequest: false,
976
- lastTextureComponents: 0,
977
- _scalars: null
984
+ lastTextureComponents: 0
985
+ // _scalars: null,
986
+ // _colorTransferFunc: null,
987
+ // _pwFunc: null,
988
+ // _labelOutlineThicknessArray: null,
978
989
  };
979
990
 
980
991
  // ----------------------------------------------------------------------------
@@ -1,4 +1,4 @@
1
- import { n as newInstance$1, o as obj, g as get, c as macro } from '../../macros2.js';
1
+ import { n as newInstance$1, o as obj, g as get, h as chain, c as macro } from '../../macros2.js';
2
2
  import { mat4, mat3, vec3 } from 'gl-matrix';
3
3
  import vtkClosedPolyLineToSurfaceFilter from '../../Filters/General/ClosedPolyLineToSurfaceFilter.js';
4
4
  import vtkCutter from '../../Filters/Core/Cutter.js';
@@ -53,6 +53,9 @@ function safeMatrixMultiply(matrixArray, matrixType, tmpMat) {
53
53
  function vtkOpenGLImageResliceMapper(publicAPI, model) {
54
54
  // Set our className
55
55
  model.classHierarchy.push('vtkOpenGLImageResliceMapper');
56
+ function unregisterGraphicsResources(renderWindow) {
57
+ [model._scalars, model._colorTransferFunc, model._pwFunc].forEach(coreObject => renderWindow.unregisterGraphicsResourceUser(coreObject, publicAPI));
58
+ }
56
59
  publicAPI.buildPass = prepass => {
57
60
  if (prepass) {
58
61
  model.currentRenderPass = null;
@@ -60,7 +63,12 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
60
63
  model._openGLRenderer = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderer');
61
64
  const ren = model._openGLRenderer.getRenderable();
62
65
  model._openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera());
66
+ const oldOglRenderWindow = model._openGLRenderWindow;
63
67
  model._openGLRenderWindow = model._openGLRenderer.getLastAncestorOfType('vtkOpenGLRenderWindow');
68
+ if (oldOglRenderWindow && !oldOglRenderWindow.isDeleted() && oldOglRenderWindow !== model._openGLRenderWindow) {
69
+ // Unregister the mapper when the render window changes
70
+ unregisterGraphicsResources(oldOglRenderWindow);
71
+ }
64
72
  model.context = model._openGLRenderWindow.getContext();
65
73
  model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
66
74
  }
@@ -174,31 +182,29 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
174
182
  if (!scalars) {
175
183
  return;
176
184
  }
177
- if (model._scalars !== scalars) {
178
- model._openGLRenderWindow.releaseGraphicsResourcesForObject(model._scalars);
179
- model._scalars = scalars;
180
- }
181
185
  const numComp = scalars.getNumberOfComponents();
182
186
  let toString = `${image.getMTime()}A${scalars.getMTime()}`;
183
187
  const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
184
- const reBuildTex = !tex?.vtkObj?.getHandle() || tex?.hash !== toString;
188
+ const reBuildTex = !tex?.oglObject?.getHandle() || tex?.hash !== toString;
185
189
  if (reBuildTex) {
186
- if (!model.openGLTexture) {
187
- model.openGLTexture = vtkOpenGLTexture.newInstance();
188
- model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
189
- }
190
+ model.openGLTexture = vtkOpenGLTexture.newInstance();
191
+ model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
190
192
  // Build the image scalar texture
191
193
  const dims = image.getDimensions();
192
194
  // Use norm16 for the 3D texture if the extension is available
193
195
  model.openGLTexture.setOglNorm16Ext(model.context.getExtension('EXT_texture_norm16'));
194
- model.openGLTexture.releaseGraphicsResources(model._openGLRenderWindow);
195
196
  model.openGLTexture.resetFormatAndType();
196
197
  model.openGLTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars);
197
198
  if (scalars) {
198
199
  model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.openGLTexture, toString);
200
+ if (scalars !== model._scalars) {
201
+ model._openGLRenderWindow.registerGraphicsResourceUser(scalars, publicAPI);
202
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._scalars, publicAPI);
203
+ }
204
+ model._scalars = scalars;
199
205
  }
200
206
  } else {
201
- model.openGLTexture = tex.vtkObj;
207
+ model.openGLTexture = tex.oglObject;
202
208
  }
203
209
  const ppty = actor.getProperty();
204
210
  const iComps = ppty.getIndependentComponents();
@@ -207,15 +213,13 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
207
213
  const colorTransferFunc = ppty.getRGBTransferFunction();
208
214
  toString = computeFnToString(ppty, colorTransferFunc, numIComps);
209
215
  const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
210
- const reBuildC = !cTex?.vtkObj?.getHandle() || cTex?.hash !== toString || model.colorTextureString !== toString;
216
+ const reBuildC = !cTex?.oglObject?.getHandle() || cTex?.hash !== toString;
211
217
  if (reBuildC) {
212
218
  const cWidth = 1024;
213
219
  const cSize = cWidth * textureHeight * 3;
214
220
  const cTable = new Uint8ClampedArray(cSize);
215
- if (!model.colorTexture) {
216
- model.colorTexture = vtkOpenGLTexture.newInstance();
217
- model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
218
- }
221
+ model.colorTexture = vtkOpenGLTexture.newInstance();
222
+ model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
219
223
  if (colorTransferFunc) {
220
224
  const tmpTable = new Float32Array(cWidth * 3);
221
225
  for (let c = 0; c < numIComps; c++) {
@@ -233,7 +237,6 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
233
237
  }
234
238
  }
235
239
  }
236
- model.colorTexture.releaseGraphicsResources(model._openGLRenderWindow);
237
240
  model.colorTexture.resetFormatAndType();
238
241
  model.colorTexture.create2DFromRaw(cWidth, textureHeight, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
239
242
  } else {
@@ -242,17 +245,19 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
242
245
  cTable[i + 1] = 255.0 * i / ((cWidth - 1) * 3);
243
246
  cTable[i + 2] = 255.0 * i / ((cWidth - 1) * 3);
244
247
  }
245
- model.colorTexture.releaseGraphicsResources(model._openGLRenderWindow);
246
248
  model.colorTexture.resetFormatAndType();
247
249
  model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
248
250
  }
249
- model.colorTextureString = toString;
250
251
  if (colorTransferFunc) {
251
- model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, model.colorTextureString);
252
+ model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, toString);
253
+ if (colorTransferFunc !== model._colorTransferFunc) {
254
+ model._openGLRenderWindow.registerGraphicsResourceUser(colorTransferFunc, publicAPI);
255
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._colorTransferFunc, publicAPI);
256
+ }
257
+ model._colorTransferFunc = colorTransferFunc;
252
258
  }
253
259
  } else {
254
- model.colorTexture = cTex.vtkObj;
255
- model.colorTextureString = cTex.hash;
260
+ model.colorTexture = cTex.oglObject;
256
261
  }
257
262
 
258
263
  // Build piecewise function buffer. This buffer is used either
@@ -262,15 +267,13 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
262
267
  toString = computeFnToString(ppty, pwFunc, numIComps);
263
268
  const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
264
269
  // rebuild opacity tfun?
265
- const reBuildPwf = !pwfTex?.vtkObj?.getHandle() || pwfTex?.hash !== toString || model.pwfTextureString !== toString;
270
+ const reBuildPwf = !pwfTex?.oglObject?.getHandle() || pwfTex?.hash !== toString;
266
271
  if (reBuildPwf) {
267
272
  const pwfWidth = 1024;
268
273
  const pwfSize = pwfWidth * textureHeight;
269
274
  const pwfTable = new Uint8ClampedArray(pwfSize);
270
- if (!model.pwfTexture) {
271
- model.pwfTexture = vtkOpenGLTexture.newInstance();
272
- model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
273
- }
275
+ model.pwfTexture = vtkOpenGLTexture.newInstance();
276
+ model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
274
277
  if (pwFunc) {
275
278
  const pwfFloatTable = new Float32Array(pwfSize);
276
279
  const tmpTable = new Float32Array(pwfWidth);
@@ -295,23 +298,24 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
295
298
  }
296
299
  }
297
300
  }
298
- model.pwfTexture.releaseGraphicsResources(model._openGLRenderWindow);
299
301
  model.pwfTexture.resetFormatAndType();
300
302
  model.pwfTexture.create2DFromRaw(pwfWidth, textureHeight, 1, VtkDataTypes.FLOAT, pwfFloatTable);
301
303
  } else {
302
304
  // default is opaque
303
305
  pwfTable.fill(255.0);
304
- model.pwfTexture.releaseGraphicsResources(model._openGLRenderWindow);
305
306
  model.pwfTexture.resetFormatAndType();
306
307
  model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable);
307
308
  }
308
- model.pwfTextureString = toString;
309
309
  if (pwFunc) {
310
- model._openGLRenderWindow.setGraphicsResourceForObject(pwFunc, model.pwfTexture, model.pwfTextureString);
310
+ model._openGLRenderWindow.setGraphicsResourceForObject(pwFunc, model.pwfTexture, toString);
311
+ if (pwFunc !== model._pwFunc) {
312
+ model._openGLRenderWindow.registerGraphicsResourceUser(pwFunc, publicAPI);
313
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._pwFunc, publicAPI);
314
+ }
315
+ model._pwFunc = pwFunc;
311
316
  }
312
317
  } else {
313
- model.pwfTexture = pwfTex.vtkObj;
314
- model.pwfTextureString = pwfTex.hash;
318
+ model.pwfTexture = pwfTex.oglObject;
315
319
  }
316
320
  const vboString = `${model.resliceGeom.getMTime()}A${model.renderable.getSlabThickness()}`;
317
321
  if (!model.tris.getCABO().getElementCount() || model.VBOBuildString !== vboString) {
@@ -854,6 +858,11 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
854
858
  model._externalOpenGLTexture = true;
855
859
  }
856
860
  };
861
+ publicAPI.delete = chain(() => {
862
+ if (model._openGLRenderWindow) {
863
+ unregisterGraphicsResources(model._openGLRenderWindow);
864
+ }
865
+ }, publicAPI.delete);
857
866
  }
858
867
 
859
868
  // ----------------------------------------------------------------------------
@@ -878,8 +887,10 @@ const DEFAULT_VALUES = {
878
887
  tris: null,
879
888
  colorTexture: null,
880
889
  pwfTexture: null,
881
- _externalOpenGLTexture: false,
882
- _scalars: null
890
+ _externalOpenGLTexture: false
891
+ // _scalars: null,
892
+ // _colorTransferFunc: null,
893
+ // _pwFunc: null,
883
894
  };
884
895
 
885
896
  // ----------------------------------------------------------------------------
@@ -441,8 +441,8 @@ export interface vtkOpenGLRenderWindow extends vtkOpenGLRenderWindowBase {
441
441
  */
442
442
  setGraphicsResourceForObject(
443
443
  vtkObj: vtkCellArray | vtkDataArray | vtkPoints,
444
- gObj: vtkOpenGLTexture | vtkBufferObject,
445
- hash: string
444
+ gObj: Nullable<vtkOpenGLTexture | vtkBufferObject>,
445
+ hash: Nullable<string>
446
446
  ): void;
447
447
 
448
448
  /**
@@ -454,9 +454,17 @@ export interface vtkOpenGLRenderWindow extends vtkOpenGLRenderWindowBase {
454
454
  * the cached resource.
455
455
  * @return {Object} Dictionary with the graphics resource and string hash
456
456
  */
457
- getGraphicsResourceForObject(
458
- vtkObj: vtkCellArray | vtkDataArray | vtkPoints
459
- ): { gObj: vtkOpenGLTexture | vtkBufferObject; hash: string };
457
+ getGraphicsResourceForObject<
458
+ T extends vtkCellArray | vtkDataArray | vtkPoints
459
+ >(
460
+ vtkObj: T
461
+ ):
462
+ | {
463
+ coreObject: T;
464
+ oglObject: Nullable<vtkOpenGLTexture | vtkBufferObject>;
465
+ hash: Nullable<string>;
466
+ }
467
+ | undefined;
460
468
 
461
469
  /**
462
470
  * Get approximate graphics memory usage, in bytes, for the context. This is a simple computation
@@ -21,7 +21,7 @@ const SCREENSHOT_PLACEHOLDER = {
21
21
  width: '100%',
22
22
  height: '100%'
23
23
  };
24
- const parentMethodsToProxy = ['activateTexture', 'deactivateTexture', 'disableCullFace', 'enableCullFace', 'get3DContext', 'getActiveFramebuffer', 'getContext', 'getDefaultTextureByteSize', 'getDefaultTextureInternalFormat', 'getDefaultToWebgl2', 'getGLInformations', 'getGraphicsMemoryInfo', 'getGraphicsResourceForObject', 'getHardwareMaximumLineWidth', 'getPixelData', 'getShaderCache', 'getTextureUnitForTexture', 'getTextureUnitManager', 'getWebgl2', 'makeCurrent', 'releaseGraphicsResources', 'releaseGraphicsResourcesForObject', 'restoreContext', 'setActiveFramebuffer', 'setContext', 'setDefaultToWebgl2', 'setGraphicsResourceForObject'];
24
+ const parentMethodsToProxy = ['activateTexture', 'deactivateTexture', 'disableCullFace', 'enableCullFace', 'get3DContext', 'getActiveFramebuffer', 'getContext', 'getDefaultTextureByteSize', 'getDefaultTextureInternalFormat', 'getDefaultToWebgl2', 'getGLInformations', 'getGraphicsMemoryInfo', 'getGraphicsResourceForObject', 'getHardwareMaximumLineWidth', 'getPixelData', 'getShaderCache', 'getTextureUnitForTexture', 'getTextureUnitManager', 'getWebgl2', 'makeCurrent', 'releaseGraphicsResources', 'registerGraphicsResourceUser', 'unregisterGraphicsResourceUser', 'restoreContext', 'setActiveFramebuffer', 'setContext', 'setDefaultToWebgl2', 'setGraphicsResourceForObject'];
25
25
  function checkRenderTargetSupport(gl, format, type) {
26
26
  // create temporary frame buffer and texture
27
27
  const framebuffer = gl.createFramebuffer();
@@ -676,49 +676,66 @@ function vtkOpenGLRenderWindow(publicAPI, model) {
676
676
  }
677
677
  return modified;
678
678
  };
679
- publicAPI.getGraphicsResourceForObject = vtkObj => {
680
- if (!vtkObj) {
681
- return null;
679
+ publicAPI.registerGraphicsResourceUser = (coreObject, newUser) => {
680
+ // Try to create the graphics resource if it doesn't exist
681
+ if (!model._graphicsResources.has(coreObject)) {
682
+ publicAPI.setGraphicsResourceForObject(coreObject, null, null);
683
+ }
684
+ // Add newUser to the set of users
685
+ const sharedResource = model._graphicsResources.get(coreObject);
686
+ sharedResource?.users.add(newUser);
687
+ };
688
+ publicAPI.unregisterGraphicsResourceUser = (coreObject, oldUser) => {
689
+ const sharedResource = model._graphicsResources.get(coreObject);
690
+ if (!sharedResource) {
691
+ return;
692
+ }
693
+ sharedResource.users.delete(oldUser);
694
+ // Release graphics resources when the number of users reaches 0
695
+ if (!sharedResource.users.size) {
696
+ sharedResource.oglObject?.releaseGraphicsResources(publicAPI);
697
+ model._graphicsResources.delete(coreObject);
682
698
  }
683
- const vtko = model._graphicsResources.get(vtkObj);
684
- const vtkh = model._graphicsResourceHash.get(vtkObj);
685
- return {
686
- vtkObj: vtko,
687
- hash: vtkh
688
- };
689
699
  };
690
- publicAPI.setGraphicsResourceForObject = (vtkObj, gObj, hash) => {
691
- if (!vtkObj) {
700
+ publicAPI.getGraphicsResourceForObject = coreObject => model._graphicsResources.get(coreObject);
701
+ publicAPI.setGraphicsResourceForObject = (coreObject, oglObject, hash) => {
702
+ if (!coreObject) {
692
703
  return;
693
704
  }
694
- model._graphicsResources.set(vtkObj, gObj);
695
- model._graphicsResourceHash.set(vtkObj, hash);
705
+ const sharedResource = model._graphicsResources.get(coreObject);
706
+ // Release the old resource
707
+ sharedResource?.oglObject?.releaseGraphicsResources(publicAPI);
708
+ // Keep the same users that have registered for this coreObject
709
+ model._graphicsResources.set(coreObject, {
710
+ coreObject,
711
+ oglObject,
712
+ hash,
713
+ users: sharedResource?.users ?? new Set()
714
+ });
696
715
  };
697
716
  publicAPI.getGraphicsMemoryInfo = () => {
698
717
  let memUsed = 0;
699
- model._graphicsResources.forEach((gObj, vtkObj) => {
700
- memUsed += gObj.getAllocatedGPUMemoryInBytes();
718
+ model._graphicsResources.forEach(_ref3 => {
719
+ let {
720
+ oglObject
721
+ } = _ref3;
722
+ memUsed += oglObject.getAllocatedGPUMemoryInBytes();
701
723
  });
702
724
  return memUsed;
703
725
  };
704
- publicAPI.releaseGraphicsResourcesForObject = vtkObj => {
705
- if (!vtkObj) {
706
- return false;
707
- }
708
- model._graphicsResources.get(vtkObj)?.releaseGraphicsResources(publicAPI);
709
- return model._graphicsResources.delete(vtkObj) && model._graphicsResourceHash.delete(vtkObj);
710
- };
711
726
  publicAPI.releaseGraphicsResources = () => {
712
727
  // Clear the shader cache
713
728
  if (model.shaderCache !== null) {
714
729
  model.shaderCache.releaseGraphicsResources(publicAPI);
715
730
  }
716
731
  // Free cached graphics resources at the context level
717
- model._graphicsResources.forEach((gObj, vtkObj) => {
718
- gObj.releaseGraphicsResources(publicAPI);
732
+ model._graphicsResources.forEach(_ref4 => {
733
+ let {
734
+ oglObject
735
+ } = _ref4;
736
+ oglObject.releaseGraphicsResources(publicAPI);
719
737
  });
720
738
  model._graphicsResources.clear();
721
- model._graphicsResourceHash.clear();
722
739
  if (model.textureUnitManager !== null) {
723
740
  model.textureUnitManager.freeAll();
724
741
  }
@@ -800,7 +817,6 @@ function extend(publicAPI, model) {
800
817
  model.bgImage.style.zIndex = '-1';
801
818
  model._textureResourceIds = new Map();
802
819
  model._graphicsResources = new Map();
803
- model._graphicsResourceHash = new Map();
804
820
  model._glInformation = null;
805
821
  model.myFactory = vtkViewNodeFactory.newInstance();
806
822
  model.shaderCache = vtkShaderCache.newInstance();
@@ -114,6 +114,9 @@ function getColorCodeFromPreset(colorMixPreset) {
114
114
  function vtkOpenGLVolumeMapper(publicAPI, model) {
115
115
  // Set our className
116
116
  model.classHierarchy.push('vtkOpenGLVolumeMapper');
117
+ function unregisterGraphicsResources(renderWindow) {
118
+ [model._scalars, model._scalarOpacityFunc, model._colorTransferFunc, model._labelOutlineThicknessArray].forEach(coreObject => renderWindow.unregisterGraphicsResourceUser(coreObject, publicAPI));
119
+ }
117
120
  publicAPI.buildPass = () => {
118
121
  model.zBufferTexture = null;
119
122
  };
@@ -133,17 +136,16 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
133
136
  // Renders myself
134
137
  publicAPI.volumePass = (prepass, renderPass) => {
135
138
  if (prepass) {
139
+ const oldOglRenderWindow = model._openGLRenderWindow;
136
140
  model._openGLRenderWindow = publicAPI.getLastAncestorOfType('vtkOpenGLRenderWindow');
141
+ if (oldOglRenderWindow && !oldOglRenderWindow.isDeleted() && oldOglRenderWindow !== model._openGLRenderWindow) {
142
+ // Unregister the mapper when the render window changes
143
+ unregisterGraphicsResources(oldOglRenderWindow);
144
+ }
137
145
  model.context = model._openGLRenderWindow.getContext();
138
146
  model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
139
147
  model.jitterTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
140
148
  model.framebuffer.setOpenGLRenderWindow(model._openGLRenderWindow);
141
-
142
- // Per Component?
143
- model.scalarTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
144
- model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
145
- model.opacityTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
146
- model.labelOutlineThicknessTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
147
149
  model.openGLVolume = publicAPI.getFirstAncestorOfType('vtkOpenGLVolume');
148
150
  const actor = model.openGLVolume.getRenderable();
149
151
  model._openGLRenderer = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderer');
@@ -796,6 +798,10 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
796
798
  model._animationRateSubscription.unsubscribe();
797
799
  model._animationRateSubscription = null;
798
800
  }
801
+ }, () => {
802
+ if (model._openGLRenderWindow) {
803
+ unregisterGraphicsResources(model._openGLRenderWindow);
804
+ }
799
805
  }, publicAPI.delete);
800
806
  publicAPI.getRenderTargetSize = () => {
801
807
  if (model._useSmallViewport) {
@@ -1018,10 +1024,6 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1018
1024
  if (!scalars) {
1019
1025
  return;
1020
1026
  }
1021
- if (model._scalars !== scalars) {
1022
- model._openGLRenderWindow.releaseGraphicsResourcesForObject(model._scalars);
1023
- model._scalars = scalars;
1024
- }
1025
1027
  const vprop = actor.getProperty();
1026
1028
  if (!model.jitterTexture.getHandle()) {
1027
1029
  const oTable = new Uint8Array(32 * 32);
@@ -1038,8 +1040,10 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1038
1040
  const scalarOpacityFunc = vprop.getScalarOpacity();
1039
1041
  const opTex = model._openGLRenderWindow.getGraphicsResourceForObject(scalarOpacityFunc);
1040
1042
  let toString = computeFnToString(scalarOpacityFunc, useIndependentComps, numIComps);
1041
- const reBuildOp = !opTex.vtkObj || opTex.hash !== toString || model.opacityTextureString !== toString;
1043
+ const reBuildOp = !opTex?.oglObject || opTex.hash !== toString;
1042
1044
  if (reBuildOp) {
1045
+ model.opacityTexture = vtkOpenGLTexture.newInstance();
1046
+ model.opacityTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
1043
1047
  // rebuild opacity tfun?
1044
1048
  const oWidth = 1024;
1045
1049
  const oSize = oWidth * 2 * numIComps;
@@ -1056,7 +1060,6 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1056
1060
  ofTable[c * oWidth * 2 + i + oWidth] = ofTable[c * oWidth * 2 + i];
1057
1061
  }
1058
1062
  }
1059
- model.opacityTexture.releaseGraphicsResources(model._openGLRenderWindow);
1060
1063
  model.opacityTexture.resetFormatAndType();
1061
1064
  model.opacityTexture.setMinificationFilter(Filter.LINEAR);
1062
1065
  model.opacityTexture.setMagnificationFilter(Filter.LINEAR);
@@ -1074,21 +1077,26 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1074
1077
  }
1075
1078
  model.opacityTexture.create2DFromRaw(oWidth, 2 * numIComps, 1, VtkDataTypes.UNSIGNED_CHAR, oTable);
1076
1079
  }
1077
- model.opacityTextureString = toString;
1078
1080
  if (scalarOpacityFunc) {
1079
- model._openGLRenderWindow.setGraphicsResourceForObject(scalarOpacityFunc, model.opacityTexture, model.opacityTextureString);
1081
+ model._openGLRenderWindow.setGraphicsResourceForObject(scalarOpacityFunc, model.opacityTexture, toString);
1082
+ if (scalarOpacityFunc !== model._scalarOpacityFunc) {
1083
+ model._openGLRenderWindow.registerGraphicsResourceUser(scalarOpacityFunc, publicAPI);
1084
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._scalarOpacityFunc, publicAPI);
1085
+ }
1086
+ model._scalarOpacityFunc = scalarOpacityFunc;
1080
1087
  }
1081
1088
  } else {
1082
- model.opacityTexture = opTex.vtkObj;
1083
- model.opacityTextureString = opTex.hash;
1089
+ model.opacityTexture = opTex.oglObject;
1084
1090
  }
1085
1091
 
1086
1092
  // rebuild color tfun?
1087
1093
  const colorTransferFunc = vprop.getRGBTransferFunction();
1088
1094
  toString = computeFnToString(colorTransferFunc, useIndependentComps, numIComps);
1089
1095
  const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
1090
- const reBuildC = !cTex?.vtkObj?.getHandle() || cTex?.hash !== toString || model.colorTextureString !== toString;
1096
+ const reBuildC = !cTex?.oglObject?.getHandle() || cTex?.hash !== toString;
1091
1097
  if (reBuildC) {
1098
+ model.colorTexture = vtkOpenGLTexture.newInstance();
1099
+ model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
1092
1100
  const cWidth = 1024;
1093
1101
  const cSize = cWidth * 2 * numIComps * 3;
1094
1102
  const cTable = new Uint8ClampedArray(cSize);
@@ -1102,37 +1110,45 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1102
1110
  cTable[c * cWidth * 6 + i + cWidth * 3] = 255.0 * tmpTable[i];
1103
1111
  }
1104
1112
  }
1105
- model.colorTexture.releaseGraphicsResources(model._openGLRenderWindow);
1106
1113
  model.colorTexture.resetFormatAndType();
1107
1114
  model.colorTexture.setMinificationFilter(Filter.LINEAR);
1108
1115
  model.colorTexture.setMagnificationFilter(Filter.LINEAR);
1109
1116
  model.colorTexture.create2DFromRaw(cWidth, 2 * numIComps, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
1110
- model.colorTextureString = toString;
1111
1117
  if (colorTransferFunc) {
1112
- model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, model.colorTextureString);
1118
+ model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, toString);
1119
+ if (colorTransferFunc !== model._colorTransferFunc) {
1120
+ model._openGLRenderWindow.registerGraphicsResourceUser(colorTransferFunc, publicAPI);
1121
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._colorTransferFunc, publicAPI);
1122
+ }
1123
+ model._colorTransferFunc = colorTransferFunc;
1113
1124
  }
1114
1125
  } else {
1115
- model.colorTexture = cTex.vtkObj;
1116
- model.colorTextureString = cTex.hash;
1126
+ model.colorTexture = cTex.oglObject;
1117
1127
  }
1118
1128
  publicAPI.updateLabelOutlineThicknessTexture(actor);
1119
1129
  const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
1120
1130
  // rebuild the scalarTexture if the data has changed
1121
1131
  toString = `${image.getMTime()}A${scalars.getMTime()}`;
1122
- const reBuildTex = !tex?.vtkObj?.getHandle() || tex?.hash !== toString;
1132
+ const reBuildTex = !tex?.oglObject?.getHandle() || tex?.hash !== toString;
1123
1133
  if (reBuildTex) {
1134
+ model.scalarTexture = vtkOpenGLTexture.newInstance();
1135
+ model.scalarTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
1124
1136
  // Build the textures
1125
1137
  const dims = image.getDimensions();
1126
1138
  // Use norm16 for scalar texture if the extension is available
1127
1139
  model.scalarTexture.setOglNorm16Ext(model.context.getExtension('EXT_texture_norm16'));
1128
- model.scalarTexture.releaseGraphicsResources(model._openGLRenderWindow);
1129
1140
  model.scalarTexture.resetFormatAndType();
1130
1141
  model.scalarTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars, model.renderable.getPreferSizeOverAccuracy());
1131
1142
  if (scalars) {
1132
1143
  model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.scalarTexture, toString);
1144
+ if (scalars !== model._scalars) {
1145
+ model._openGLRenderWindow.registerGraphicsResourceUser(scalars, publicAPI);
1146
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._scalars, publicAPI);
1147
+ }
1148
+ model._scalars = scalars;
1133
1149
  }
1134
1150
  } else {
1135
- model.scalarTexture = tex.vtkObj;
1151
+ model.scalarTexture = tex.oglObject;
1136
1152
  }
1137
1153
  if (!model.tris.getCABO().getElementCount()) {
1138
1154
  // build the CABO
@@ -1202,8 +1218,10 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1202
1218
  // we can use it to decide whether to rebuild the labelOutlineThicknessTexture
1203
1219
  // or not
1204
1220
  const toString = `${labelOutlineThicknessArray.join('-')}`;
1205
- const reBuildL = !lTex?.vtkObj?.getHandle() || lTex?.hash !== toString || model.labelOutlineThicknessTextureString !== toString;
1221
+ const reBuildL = !lTex?.oglObject?.getHandle() || lTex?.hash !== toString;
1206
1222
  if (reBuildL) {
1223
+ model.labelOutlineThicknessTexture = vtkOpenGLTexture.newInstance();
1224
+ model.labelOutlineThicknessTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
1207
1225
  const lWidth = 1024;
1208
1226
  const lHeight = 1;
1209
1227
  const lSize = lWidth * lHeight;
@@ -1216,20 +1234,22 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1216
1234
  const thickness = typeof labelOutlineThicknessArray[i] !== 'undefined' ? labelOutlineThicknessArray[i] : labelOutlineThicknessArray[0];
1217
1235
  lTable[i] = thickness;
1218
1236
  }
1219
- model.labelOutlineThicknessTexture.releaseGraphicsResources(model._openGLRenderWindow);
1220
1237
  model.labelOutlineThicknessTexture.resetFormatAndType();
1221
1238
  model.labelOutlineThicknessTexture.setMinificationFilter(Filter.NEAREST);
1222
1239
  model.labelOutlineThicknessTexture.setMagnificationFilter(Filter.NEAREST);
1223
1240
 
1224
1241
  // Create a 2D texture (acting as 1D) from the raw data
1225
1242
  model.labelOutlineThicknessTexture.create2DFromRaw(lWidth, lHeight, 1, VtkDataTypes.UNSIGNED_CHAR, lTable);
1226
- model.labelOutlineThicknessTextureString = toString;
1227
1243
  if (labelOutlineThicknessArray) {
1228
- model._openGLRenderWindow.setGraphicsResourceForObject(labelOutlineThicknessArray, model.labelOutlineThicknessTexture, model.labelOutlineThicknessTextureString);
1244
+ model._openGLRenderWindow.setGraphicsResourceForObject(labelOutlineThicknessArray, model.labelOutlineThicknessTexture, toString);
1245
+ if (labelOutlineThicknessArray !== model._labelOutlineThicknessArray) {
1246
+ model._openGLRenderWindow.registerGraphicsResourceUser(labelOutlineThicknessArray, publicAPI);
1247
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._labelOutlineThicknessArray, publicAPI);
1248
+ }
1249
+ model._labelOutlineThicknessArray = labelOutlineThicknessArray;
1229
1250
  }
1230
1251
  } else {
1231
- model.labelOutlineThicknessTexture = lTex.vtkObj;
1232
- model.labelOutlineThicknessTextureString = lTex.hash;
1252
+ model.labelOutlineThicknessTexture = lTex.oglObject;
1233
1253
  }
1234
1254
  };
1235
1255
  }
@@ -1264,8 +1284,11 @@ const DEFAULT_VALUES = {
1264
1284
  modelToView: null,
1265
1285
  projectionToView: null,
1266
1286
  avgWindowArea: 0.0,
1267
- avgFrameTime: 0.0,
1268
- _scalars: null
1287
+ avgFrameTime: 0.0
1288
+ // _scalars: null,
1289
+ // _scalarOpacityFunc: null,
1290
+ // _colorTransferFunc: null,
1291
+ // _labelOutlineThicknessArray: null,
1269
1292
  };
1270
1293
 
1271
1294
  // ----------------------------------------------------------------------------
@@ -1282,13 +1305,9 @@ function extend(publicAPI, model) {
1282
1305
  mtime: 0
1283
1306
  });
1284
1307
  model.tris = vtkHelper.newInstance();
1285
- model.scalarTexture = vtkOpenGLTexture.newInstance();
1286
- model.opacityTexture = vtkOpenGLTexture.newInstance();
1287
- model.colorTexture = vtkOpenGLTexture.newInstance();
1288
1308
  model.jitterTexture = vtkOpenGLTexture.newInstance();
1289
1309
  model.jitterTexture.setWrapS(Wrap.REPEAT);
1290
1310
  model.jitterTexture.setWrapT(Wrap.REPEAT);
1291
- model.labelOutlineThicknessTexture = vtkOpenGLTexture.newInstance();
1292
1311
  model.framebuffer = vtkOpenGLFramebuffer.newInstance();
1293
1312
  model.idxToView = mat4.identity(new Float64Array(16));
1294
1313
  model.idxNormalMatrix = mat3.identity(new Float64Array(9));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitware/vtk.js",
3
- "version": "30.9.3",
3
+ "version": "31.0.0",
4
4
  "description": "Visualization Toolkit for the Web",
5
5
  "keywords": [
6
6
  "3d",