@kitware/vtk.js 28.12.5 → 28.13.1
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/Interaction/UI/FPSMonitor.js +1 -0
- package/Proxy/Core/View2DProxy.js +3 -0
- package/Rendering/Core/ImageProperty.js +14 -5
- package/Rendering/Core/Mapper2D.js +10 -0
- package/Rendering/Core/RenderWindow.js +17 -8
- package/Rendering/Core/VolumeProperty.js +20 -8
- package/Rendering/OpenGL/BufferObject.js +5 -2
- package/Rendering/OpenGL/Helper.js +1 -0
- package/Rendering/OpenGL/ImageMapper.js +83 -43
- package/Rendering/OpenGL/ImageResliceMapper.js +76 -40
- package/Rendering/OpenGL/PolyDataMapper.js +8 -0
- package/Rendering/OpenGL/PolyDataMapper2D.js +8 -0
- package/Rendering/OpenGL/RenderWindow.d.ts +37 -1
- package/Rendering/OpenGL/RenderWindow.js +84 -0
- package/Rendering/OpenGL/Renderer.js +7 -1
- package/Rendering/OpenGL/ShaderCache.js +23 -22
- package/Rendering/OpenGL/ShaderProgram.js +12 -2
- package/Rendering/OpenGL/Texture.js +9 -3
- package/Rendering/OpenGL/TextureUnitManager.js +5 -0
- package/Rendering/OpenGL/VolumeMapper.js +52 -11
- package/package.json +1 -1
|
@@ -257,6 +257,9 @@ function vtkView2DProxy(publicAPI, model) {
|
|
|
257
257
|
}
|
|
258
258
|
publicAPI.bindRepresentationToManipulator = representation => {
|
|
259
259
|
let nbListeners = 0;
|
|
260
|
+
if (!representation.getProxyId) {
|
|
261
|
+
return nbListeners;
|
|
262
|
+
}
|
|
260
263
|
model.rangeManipulator.removeAllListeners();
|
|
261
264
|
model.sliceRepresentation = representation;
|
|
262
265
|
while (model.sliceRepresentationSubscriptions.length) {
|
|
@@ -38,7 +38,9 @@ function vtkImageProperty(publicAPI, model) {
|
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
// Set the color of a volume to an RGB transfer function
|
|
41
|
-
publicAPI.setRGBTransferFunction = (
|
|
41
|
+
publicAPI.setRGBTransferFunction = function () {
|
|
42
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
43
|
+
let func = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
42
44
|
// backwards compatible call without the component index
|
|
43
45
|
let idx = index;
|
|
44
46
|
let transferFunc = func;
|
|
@@ -61,7 +63,9 @@ function vtkImageProperty(publicAPI, model) {
|
|
|
61
63
|
};
|
|
62
64
|
|
|
63
65
|
// Set the piecewise function
|
|
64
|
-
publicAPI.setPiecewiseFunction = (
|
|
66
|
+
publicAPI.setPiecewiseFunction = function () {
|
|
67
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
68
|
+
let func = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
65
69
|
let idx = index;
|
|
66
70
|
let transferFunc = func;
|
|
67
71
|
if (!Number.isInteger(index)) {
|
|
@@ -83,7 +87,9 @@ function vtkImageProperty(publicAPI, model) {
|
|
|
83
87
|
};
|
|
84
88
|
|
|
85
89
|
// Alias to set the piecewise function
|
|
86
|
-
publicAPI.setScalarOpacity = (
|
|
90
|
+
publicAPI.setScalarOpacity = function () {
|
|
91
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
92
|
+
let func = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
87
93
|
// backwards compatible call without the component index
|
|
88
94
|
let idx = index;
|
|
89
95
|
let transferFunc = func;
|
|
@@ -99,7 +105,9 @@ function vtkImageProperty(publicAPI, model) {
|
|
|
99
105
|
let idx = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
100
106
|
return publicAPI.getPiecewiseFunction(idx);
|
|
101
107
|
};
|
|
102
|
-
publicAPI.setComponentWeight = (
|
|
108
|
+
publicAPI.setComponentWeight = function () {
|
|
109
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
110
|
+
let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
103
111
|
if (index < 0 || index >= VTK_MAX_VRCOMP) {
|
|
104
112
|
vtkErrorMacro('Invalid index');
|
|
105
113
|
return false;
|
|
@@ -112,7 +120,8 @@ function vtkImageProperty(publicAPI, model) {
|
|
|
112
120
|
}
|
|
113
121
|
return false;
|
|
114
122
|
};
|
|
115
|
-
publicAPI.getComponentWeight =
|
|
123
|
+
publicAPI.getComponentWeight = function () {
|
|
124
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
116
125
|
if (index < 0 || index >= VTK_MAX_VRCOMP) {
|
|
117
126
|
vtkErrorMacro('Invalid index');
|
|
118
127
|
return 0.0;
|
|
@@ -116,6 +116,16 @@ function vtkMapper2D(publicAPI, model) {
|
|
|
116
116
|
}
|
|
117
117
|
model.colorBuildString = `${publicAPI.getMTime()}${scalars.getMTime()}${alpha}`;
|
|
118
118
|
};
|
|
119
|
+
publicAPI.getPrimitiveCount = () => {
|
|
120
|
+
const input = publicAPI.getInputData();
|
|
121
|
+
const pcount = {
|
|
122
|
+
points: input.getPoints().getNumberOfValues() / 3,
|
|
123
|
+
verts: input.getVerts().getNumberOfValues() - input.getVerts().getNumberOfCells(),
|
|
124
|
+
lines: input.getLines().getNumberOfValues() - 2 * input.getLines().getNumberOfCells(),
|
|
125
|
+
triangles: input.getPolys().getNumberOfValues() - 3 * input.getPolys().getNumberOfCells()
|
|
126
|
+
};
|
|
127
|
+
return pcount;
|
|
128
|
+
};
|
|
119
129
|
}
|
|
120
130
|
|
|
121
131
|
// ----------------------------------------------------------------------------
|
|
@@ -94,22 +94,31 @@ function vtkRenderWindow(publicAPI, model) {
|
|
|
94
94
|
publicAPI.getStatistics = () => {
|
|
95
95
|
const results = {
|
|
96
96
|
propCount: 0,
|
|
97
|
-
invisiblePropCount: 0
|
|
97
|
+
invisiblePropCount: 0,
|
|
98
|
+
gpuMemoryMB: 0
|
|
98
99
|
};
|
|
100
|
+
model._views.forEach(v => {
|
|
101
|
+
results.gpuMemoryMB += v.getGraphicsMemoryInfo() / 1e6;
|
|
102
|
+
});
|
|
99
103
|
model.renderers.forEach(ren => {
|
|
100
104
|
const props = ren.getViewProps();
|
|
105
|
+
const gren = model._views[0].getViewNodeFor(ren);
|
|
101
106
|
props.forEach(prop => {
|
|
102
107
|
if (prop.getVisibility()) {
|
|
103
108
|
results.propCount += 1;
|
|
104
109
|
const mpr = prop.getMapper && prop.getMapper();
|
|
105
110
|
if (mpr && mpr.getPrimitiveCount) {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
const gmpr = gren.getViewNodeFor(mpr);
|
|
112
|
+
if (gmpr) {
|
|
113
|
+
results.gpuMemoryMB += gmpr.getAllocatedGPUMemoryInBytes() / 1e6;
|
|
114
|
+
const pcount = mpr.getPrimitiveCount();
|
|
115
|
+
Object.keys(pcount).forEach(keyName => {
|
|
116
|
+
if (!results[keyName]) {
|
|
117
|
+
results[keyName] = 0;
|
|
118
|
+
}
|
|
119
|
+
results[keyName] += pcount[keyName];
|
|
120
|
+
});
|
|
121
|
+
}
|
|
113
122
|
}
|
|
114
123
|
} else {
|
|
115
124
|
results.invisiblePropCount += 1;
|
|
@@ -63,7 +63,9 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
// Set the color of a volume to a gray transfer function
|
|
66
|
-
publicAPI.setGrayTransferFunction = (
|
|
66
|
+
publicAPI.setGrayTransferFunction = function () {
|
|
67
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
68
|
+
let func = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
67
69
|
let modified = false;
|
|
68
70
|
if (model.componentData[index].grayTransferFunction !== func) {
|
|
69
71
|
model.componentData[index].grayTransferFunction = func;
|
|
@@ -80,7 +82,8 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
80
82
|
};
|
|
81
83
|
|
|
82
84
|
// Get the currently set gray transfer function. Create one if none set.
|
|
83
|
-
publicAPI.getGrayTransferFunction =
|
|
85
|
+
publicAPI.getGrayTransferFunction = function () {
|
|
86
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
84
87
|
if (model.componentData[index].grayTransferFunction === null) {
|
|
85
88
|
model.componentData[index].grayTransferFunction = vtkPiecewiseFunction.newInstance();
|
|
86
89
|
model.componentData[index].grayTransferFunction.addPoint(0, 0.0);
|
|
@@ -94,7 +97,9 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
94
97
|
};
|
|
95
98
|
|
|
96
99
|
// Set the color of a volume to an RGB transfer function
|
|
97
|
-
publicAPI.setRGBTransferFunction = (
|
|
100
|
+
publicAPI.setRGBTransferFunction = function () {
|
|
101
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
102
|
+
let func = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
98
103
|
let modified = false;
|
|
99
104
|
if (model.componentData[index].rGBTransferFunction !== func) {
|
|
100
105
|
model.componentData[index].rGBTransferFunction = func;
|
|
@@ -111,7 +116,8 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
111
116
|
};
|
|
112
117
|
|
|
113
118
|
// Get the currently set RGB transfer function. Create one if none set.
|
|
114
|
-
publicAPI.getRGBTransferFunction =
|
|
119
|
+
publicAPI.getRGBTransferFunction = function () {
|
|
120
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
115
121
|
if (model.componentData[index].rGBTransferFunction === null) {
|
|
116
122
|
model.componentData[index].rGBTransferFunction = vtkColorTransferFunction.newInstance();
|
|
117
123
|
model.componentData[index].rGBTransferFunction.addRGBPoint(0, 0.0, 0.0, 0.0);
|
|
@@ -125,7 +131,9 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
125
131
|
};
|
|
126
132
|
|
|
127
133
|
// Set the scalar opacity of a volume to a transfer function
|
|
128
|
-
publicAPI.setScalarOpacity = (
|
|
134
|
+
publicAPI.setScalarOpacity = function () {
|
|
135
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
136
|
+
let func = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
129
137
|
if (model.componentData[index].scalarOpacity !== func) {
|
|
130
138
|
model.componentData[index].scalarOpacity = func;
|
|
131
139
|
publicAPI.modified();
|
|
@@ -135,7 +143,8 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
135
143
|
};
|
|
136
144
|
|
|
137
145
|
// Get the scalar opacity transfer function. Create one if none set.
|
|
138
|
-
publicAPI.getScalarOpacity =
|
|
146
|
+
publicAPI.getScalarOpacity = function () {
|
|
147
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
139
148
|
if (model.componentData[index].scalarOpacity === null) {
|
|
140
149
|
model.componentData[index].scalarOpacity = vtkPiecewiseFunction.newInstance();
|
|
141
150
|
model.componentData[index].scalarOpacity.addPoint(0, 1.0);
|
|
@@ -144,7 +153,9 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
144
153
|
}
|
|
145
154
|
return model.componentData[index].scalarOpacity;
|
|
146
155
|
};
|
|
147
|
-
publicAPI.setComponentWeight = (
|
|
156
|
+
publicAPI.setComponentWeight = function () {
|
|
157
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
158
|
+
let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
148
159
|
if (index < 0 || index >= VTK_MAX_VRCOMP) {
|
|
149
160
|
vtkErrorMacro('Invalid index');
|
|
150
161
|
return false;
|
|
@@ -157,7 +168,8 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
157
168
|
}
|
|
158
169
|
return false;
|
|
159
170
|
};
|
|
160
|
-
publicAPI.getComponentWeight =
|
|
171
|
+
publicAPI.getComponentWeight = function () {
|
|
172
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
161
173
|
if (index < 0 || index >= VTK_MAX_VRCOMP) {
|
|
162
174
|
vtkErrorMacro('Invalid index');
|
|
163
175
|
return 0.0;
|
|
@@ -70,6 +70,7 @@ function vtkOpenGLBufferObject(publicAPI, model) {
|
|
|
70
70
|
}
|
|
71
71
|
model.context.bindBuffer(convertType(internalType), internalHandle);
|
|
72
72
|
model.context.bufferData(convertType(internalType), data, model.context.STATIC_DRAW);
|
|
73
|
+
model.allocatedGPUMemoryInBytes = data.length * data.BYTES_PER_ELEMENT;
|
|
73
74
|
dirty = false;
|
|
74
75
|
return true;
|
|
75
76
|
};
|
|
@@ -92,6 +93,7 @@ function vtkOpenGLBufferObject(publicAPI, model) {
|
|
|
92
93
|
model.context.bindBuffer(convertType(internalType), null);
|
|
93
94
|
model.context.deleteBuffer(internalHandle);
|
|
94
95
|
internalHandle = null;
|
|
96
|
+
model.allocatedGPUMemoryInBytes = 0;
|
|
95
97
|
}
|
|
96
98
|
};
|
|
97
99
|
publicAPI.setOpenGLRenderWindow = rw => {
|
|
@@ -115,7 +117,8 @@ function vtkOpenGLBufferObject(publicAPI, model) {
|
|
|
115
117
|
const DEFAULT_VALUES = {
|
|
116
118
|
objectType: ObjectType.ARRAY_BUFFER,
|
|
117
119
|
// _openGLRenderWindow: null,
|
|
118
|
-
context: null
|
|
120
|
+
context: null,
|
|
121
|
+
allocatedGPUMemoryInBytes: 0
|
|
119
122
|
};
|
|
120
123
|
|
|
121
124
|
// ----------------------------------------------------------------------------
|
|
@@ -126,7 +129,7 @@ function extend(publicAPI, model) {
|
|
|
126
129
|
|
|
127
130
|
// Object methods
|
|
128
131
|
macro.obj(publicAPI, model);
|
|
129
|
-
macro.get(publicAPI, model, ['_openGLRenderWindow']);
|
|
132
|
+
macro.get(publicAPI, model, ['_openGLRenderWindow', 'allocatedGPUMemoryInBytes']);
|
|
130
133
|
macro.moveToProtected(publicAPI, model, ['openGLRenderWindow']);
|
|
131
134
|
vtkOpenGLBufferObject(publicAPI, model);
|
|
132
135
|
}
|
|
@@ -168,6 +168,7 @@ function vtkOpenGLHelper(publicAPI, model) {
|
|
|
168
168
|
}
|
|
169
169
|
return 6;
|
|
170
170
|
};
|
|
171
|
+
publicAPI.getAllocatedGPUMemoryInBytes = () => publicAPI.getCABO().getAllocatedGPUMemoryInBytes();
|
|
171
172
|
}
|
|
172
173
|
|
|
173
174
|
// ----------------------------------------------------------------------------
|
|
@@ -27,11 +27,10 @@ const {
|
|
|
27
27
|
// helper methods
|
|
28
28
|
// ----------------------------------------------------------------------------
|
|
29
29
|
|
|
30
|
-
function computeFnToString(property,
|
|
31
|
-
const pwfun = fn.apply(property);
|
|
30
|
+
function computeFnToString(property, pwfun, numberOfComponents) {
|
|
32
31
|
if (pwfun) {
|
|
33
32
|
const iComps = property.getIndependentComponents();
|
|
34
|
-
return `${
|
|
33
|
+
return `${pwfun.getMTime()}-${iComps}-${numberOfComponents}`;
|
|
35
34
|
}
|
|
36
35
|
return '0';
|
|
37
36
|
}
|
|
@@ -51,9 +50,6 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
51
50
|
model._openGLRenderWindow = model._openGLRenderer.getParent();
|
|
52
51
|
model.context = model._openGLRenderWindow.getContext();
|
|
53
52
|
model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
54
|
-
model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
55
|
-
model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
56
|
-
model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
57
53
|
const ren = model._openGLRenderer.getRenderable();
|
|
58
54
|
model.openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera());
|
|
59
55
|
// is slice set by the camera
|
|
@@ -226,7 +222,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
226
222
|
if (!model.currentRenderPass && model.lastRenderPassShaderReplacement || model.currentRenderPass && model.currentRenderPass.getShaderReplacement() !== model.lastRenderPassShaderReplacement) {
|
|
227
223
|
needRebuild = true;
|
|
228
224
|
}
|
|
229
|
-
if (needRebuild || model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || cellBO.getProgram() === 0 || model.lastTextureComponents !== tNumComp || model.lastIndependentComponents !== iComp) {
|
|
225
|
+
if (needRebuild || model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || cellBO.getProgram()?.getHandle() === 0 || model.lastTextureComponents !== tNumComp || model.lastIndependentComponents !== iComp) {
|
|
230
226
|
model.lastHaveSeenDepthRequest = model.haveSeenDepthRequest;
|
|
231
227
|
model.lastTextureComponents = tNumComp;
|
|
232
228
|
model.lastIndependentComponents = iComp;
|
|
@@ -474,33 +470,36 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
474
470
|
const dataType = imgScalars.getDataType();
|
|
475
471
|
const numComp = imgScalars.getNumberOfComponents();
|
|
476
472
|
const actorProperty = actor.getProperty();
|
|
477
|
-
|
|
478
|
-
// set interpolation on the texture based on property setting
|
|
479
473
|
const iType = actorProperty.getInterpolationType();
|
|
480
|
-
if (iType === InterpolationType.NEAREST) {
|
|
481
|
-
model.colorTexture.setMinificationFilter(Filter.NEAREST);
|
|
482
|
-
model.colorTexture.setMagnificationFilter(Filter.NEAREST);
|
|
483
|
-
model.pwfTexture.setMinificationFilter(Filter.NEAREST);
|
|
484
|
-
model.pwfTexture.setMagnificationFilter(Filter.NEAREST);
|
|
485
|
-
} else {
|
|
486
|
-
model.colorTexture.setMinificationFilter(Filter.LINEAR);
|
|
487
|
-
model.colorTexture.setMagnificationFilter(Filter.LINEAR);
|
|
488
|
-
model.pwfTexture.setMinificationFilter(Filter.LINEAR);
|
|
489
|
-
model.pwfTexture.setMagnificationFilter(Filter.LINEAR);
|
|
490
|
-
}
|
|
491
474
|
const iComps = actorProperty.getIndependentComponents();
|
|
492
475
|
const numIComps = iComps ? numComp : 1;
|
|
493
476
|
const textureHeight = iComps ? 2 * numIComps : 1;
|
|
494
|
-
const
|
|
495
|
-
|
|
477
|
+
const colorTransferFunc = actorProperty.getRGBTransferFunction();
|
|
478
|
+
const cfunToString = computeFnToString(actorProperty, colorTransferFunc, numIComps);
|
|
479
|
+
const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
|
|
480
|
+
const reBuildC = !cTex?.vtkObj || cTex?.hash !== cfunToString || model.colorTextureString !== cfunToString;
|
|
481
|
+
if (reBuildC) {
|
|
496
482
|
const cWidth = 1024;
|
|
497
483
|
const cSize = cWidth * textureHeight * 3;
|
|
498
484
|
const cTable = new Uint8Array(cSize);
|
|
499
|
-
|
|
500
|
-
|
|
485
|
+
if (!model.colorTexture) {
|
|
486
|
+
model.colorTexture = vtkOpenGLTexture.newInstance({
|
|
487
|
+
resizable: true
|
|
488
|
+
});
|
|
489
|
+
model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
490
|
+
}
|
|
491
|
+
// set interpolation on the texture based on property setting
|
|
492
|
+
if (iType === InterpolationType.NEAREST) {
|
|
493
|
+
model.colorTexture.setMinificationFilter(Filter.NEAREST);
|
|
494
|
+
model.colorTexture.setMagnificationFilter(Filter.NEAREST);
|
|
495
|
+
} else {
|
|
496
|
+
model.colorTexture.setMinificationFilter(Filter.LINEAR);
|
|
497
|
+
model.colorTexture.setMagnificationFilter(Filter.LINEAR);
|
|
498
|
+
}
|
|
499
|
+
if (colorTransferFunc) {
|
|
501
500
|
const tmpTable = new Float32Array(cWidth * 3);
|
|
502
501
|
for (let c = 0; c < numIComps; c++) {
|
|
503
|
-
cfun = actorProperty.getRGBTransferFunction(c);
|
|
502
|
+
const cfun = actorProperty.getRGBTransferFunction(c);
|
|
504
503
|
const cRange = cfun.getRange();
|
|
505
504
|
cfun.getTable(cRange[0], cRange[1], cWidth, tmpTable, 1);
|
|
506
505
|
if (iComps) {
|
|
@@ -514,6 +513,8 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
514
513
|
}
|
|
515
514
|
}
|
|
516
515
|
}
|
|
516
|
+
model.colorTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
517
|
+
model.colorTexture.resetFormatAndType();
|
|
517
518
|
model.colorTexture.create2DFromRaw(cWidth, textureHeight, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
518
519
|
} else {
|
|
519
520
|
for (let i = 0; i < cWidth * 3; ++i) {
|
|
@@ -524,24 +525,45 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
524
525
|
model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
525
526
|
}
|
|
526
527
|
model.colorTextureString = cfunToString;
|
|
528
|
+
if (colorTransferFunc) {
|
|
529
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, model.colorTextureString);
|
|
530
|
+
}
|
|
531
|
+
} else {
|
|
532
|
+
model.colorTexture = cTex.vtkObj;
|
|
533
|
+
model.colorTextureString = cTex.hash;
|
|
527
534
|
}
|
|
528
535
|
|
|
529
536
|
// Build piecewise function buffer. This buffer is used either
|
|
530
537
|
// for component weighting or opacity, depending on whether we're
|
|
531
538
|
// rendering components independently or not.
|
|
532
|
-
const
|
|
533
|
-
|
|
539
|
+
const pwFunc = actorProperty.getPiecewiseFunction();
|
|
540
|
+
const pwfunToString = computeFnToString(actorProperty, pwFunc, numIComps);
|
|
541
|
+
const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
|
|
542
|
+
// rebuild opacity tfun?
|
|
543
|
+
const reBuildPwf = !pwfTex?.vtkObj || pwfTex?.hash !== pwfunToString || model.pwfTextureString !== pwfunToString;
|
|
544
|
+
if (reBuildPwf) {
|
|
534
545
|
const pwfWidth = 1024;
|
|
535
546
|
const pwfSize = pwfWidth * textureHeight;
|
|
536
547
|
const pwfTable = new Uint8Array(pwfSize);
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
548
|
+
if (!model.pwfTexture) {
|
|
549
|
+
model.pwfTexture = vtkOpenGLTexture.newInstance({
|
|
550
|
+
resizable: true
|
|
551
|
+
});
|
|
552
|
+
model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
553
|
+
}
|
|
554
|
+
// set interpolation on the texture based on property setting
|
|
555
|
+
if (iType === InterpolationType.NEAREST) {
|
|
556
|
+
model.pwfTexture.setMinificationFilter(Filter.NEAREST);
|
|
557
|
+
model.pwfTexture.setMagnificationFilter(Filter.NEAREST);
|
|
558
|
+
} else {
|
|
559
|
+
model.pwfTexture.setMinificationFilter(Filter.LINEAR);
|
|
560
|
+
model.pwfTexture.setMagnificationFilter(Filter.LINEAR);
|
|
561
|
+
}
|
|
562
|
+
if (pwFunc) {
|
|
541
563
|
const pwfFloatTable = new Float32Array(pwfSize);
|
|
542
564
|
const tmpTable = new Float32Array(pwfWidth);
|
|
543
565
|
for (let c = 0; c < numIComps; ++c) {
|
|
544
|
-
pwfun = actorProperty.getPiecewiseFunction(c);
|
|
566
|
+
const pwfun = actorProperty.getPiecewiseFunction(c);
|
|
545
567
|
if (pwfun === null) {
|
|
546
568
|
// Piecewise constant max if no function supplied for this component
|
|
547
569
|
pwfFloatTable.fill(1.0);
|
|
@@ -561,6 +583,8 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
561
583
|
}
|
|
562
584
|
}
|
|
563
585
|
}
|
|
586
|
+
model.pwfTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
587
|
+
model.pwfTexture.resetFormatAndType();
|
|
564
588
|
model.pwfTexture.create2DFromRaw(pwfWidth, textureHeight, 1, VtkDataTypes.FLOAT, pwfFloatTable);
|
|
565
589
|
} else {
|
|
566
590
|
// default is opaque
|
|
@@ -568,6 +592,12 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
568
592
|
model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable);
|
|
569
593
|
}
|
|
570
594
|
model.pwfTextureString = pwfunToString;
|
|
595
|
+
if (pwFunc) {
|
|
596
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(pwFunc, model.pwfTexture, model.pwfTextureString);
|
|
597
|
+
}
|
|
598
|
+
} else {
|
|
599
|
+
model.pwfTexture = pwfTex.vtkObj;
|
|
600
|
+
model.pwfTextureString = pwfTex.hash;
|
|
571
601
|
}
|
|
572
602
|
|
|
573
603
|
// Find what IJK axis and what direction to slice along
|
|
@@ -605,6 +635,12 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
605
635
|
if (model.VBOBuildString !== toString) {
|
|
606
636
|
// Build the VBOs
|
|
607
637
|
const dims = image.getDimensions();
|
|
638
|
+
if (!model.openGLTexture) {
|
|
639
|
+
model.openGLTexture = vtkOpenGLTexture.newInstance({
|
|
640
|
+
resizable: true
|
|
641
|
+
});
|
|
642
|
+
model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
643
|
+
}
|
|
608
644
|
if (iType === InterpolationType.NEAREST) {
|
|
609
645
|
if (new Set([1, 3, 4]).has(numComp) && dataType === VtkDataTypes.UNSIGNED_CHAR && !iComps) {
|
|
610
646
|
model.openGLTexture.setGenerateMipmap(true);
|
|
@@ -710,7 +746,19 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
710
746
|
} else {
|
|
711
747
|
vtkErrorMacro('Reformat slicing not yet supported.');
|
|
712
748
|
}
|
|
713
|
-
|
|
749
|
+
const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
|
|
750
|
+
if (!tex?.vtkObj) {
|
|
751
|
+
if (model._scalars !== scalars) {
|
|
752
|
+
model._openGLRenderWindow.releaseGraphicsResourcesForObject(model._scalars);
|
|
753
|
+
model._scalars = scalars;
|
|
754
|
+
}
|
|
755
|
+
model.openGLTexture.resetFormatAndType();
|
|
756
|
+
model.openGLTexture.create2DFilterableFromRaw(dims[0], dims[1], numComp, imgScalars.getDataType(), scalars, model.renderable.getPreferSizeOverAccuracy?.());
|
|
757
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.openGLTexture, model.VBOBuildString);
|
|
758
|
+
} else {
|
|
759
|
+
model.openGLTexture = tex.vtkObj;
|
|
760
|
+
model.VBOBuildString = tex.hash;
|
|
761
|
+
}
|
|
714
762
|
model.openGLTexture.activate();
|
|
715
763
|
model.openGLTexture.sendParameters();
|
|
716
764
|
model.openGLTexture.deactivate();
|
|
@@ -763,7 +811,8 @@ const DEFAULT_VALUES = {
|
|
|
763
811
|
pwfTexture: null,
|
|
764
812
|
lastHaveSeenDepthRequest: false,
|
|
765
813
|
haveSeenDepthRequest: false,
|
|
766
|
-
lastTextureComponents: 0
|
|
814
|
+
lastTextureComponents: 0,
|
|
815
|
+
_scalars: null
|
|
767
816
|
};
|
|
768
817
|
|
|
769
818
|
// ----------------------------------------------------------------------------
|
|
@@ -777,15 +826,6 @@ function extend(publicAPI, model) {
|
|
|
777
826
|
vtkReplacementShaderMapper.implementReplaceShaderCoincidentOffset(publicAPI, model, initialValues);
|
|
778
827
|
vtkReplacementShaderMapper.implementBuildShadersWithReplacements(publicAPI, model, initialValues);
|
|
779
828
|
model.tris = vtkHelper.newInstance();
|
|
780
|
-
model.openGLTexture = vtkOpenGLTexture.newInstance({
|
|
781
|
-
resizable: true
|
|
782
|
-
});
|
|
783
|
-
model.colorTexture = vtkOpenGLTexture.newInstance({
|
|
784
|
-
resizable: true
|
|
785
|
-
});
|
|
786
|
-
model.pwfTexture = vtkOpenGLTexture.newInstance({
|
|
787
|
-
resizable: true
|
|
788
|
-
});
|
|
789
829
|
model.imagemat = mat4.identity(new Float64Array(16));
|
|
790
830
|
model.imagematinv = mat4.identity(new Float64Array(16));
|
|
791
831
|
|
|
@@ -29,11 +29,10 @@ const {
|
|
|
29
29
|
// helper methods
|
|
30
30
|
// ----------------------------------------------------------------------------
|
|
31
31
|
|
|
32
|
-
function computeFnToString(property,
|
|
33
|
-
const pwfun = fn.apply(property);
|
|
32
|
+
function computeFnToString(property, pwfun, numberOfComponents) {
|
|
34
33
|
if (pwfun) {
|
|
35
34
|
const iComps = property.getIndependentComponents();
|
|
36
|
-
return `${
|
|
35
|
+
return `${pwfun.getMTime()}-${iComps}-${numberOfComponents}`;
|
|
37
36
|
}
|
|
38
37
|
return '0';
|
|
39
38
|
}
|
|
@@ -64,12 +63,6 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
64
63
|
model._openGLRenderWindow = model._openGLRenderer.getParent();
|
|
65
64
|
model.context = model._openGLRenderWindow.getContext();
|
|
66
65
|
model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
67
|
-
if (!model.openGLTexture) {
|
|
68
|
-
model.openGLTexture = vtkOpenGLTexture.newInstance();
|
|
69
|
-
}
|
|
70
|
-
model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
71
|
-
model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
72
|
-
model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
73
66
|
}
|
|
74
67
|
};
|
|
75
68
|
publicAPI.translucentPass = (prepass, renderPass) => {
|
|
@@ -181,34 +174,54 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
181
174
|
if (!scalars) {
|
|
182
175
|
return;
|
|
183
176
|
}
|
|
177
|
+
if (model._scalars !== scalars) {
|
|
178
|
+
model._openGLRenderWindow.releaseGraphicsResourcesForObject(model._scalars);
|
|
179
|
+
model._scalars = scalars;
|
|
180
|
+
}
|
|
184
181
|
const numComp = scalars.getNumberOfComponents();
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
model.openGLTexture.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
182
|
+
let toString = `${image.getMTime()}A${scalars.getMTime()}`;
|
|
183
|
+
const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
|
|
184
|
+
const reBuildTex = !tex?.vtkObj || tex?.hash !== toString || model.openGLTextureString !== toString;
|
|
185
|
+
if (reBuildTex) {
|
|
186
|
+
if (!model.openGLTexture) {
|
|
187
|
+
model.openGLTexture = vtkOpenGLTexture.newInstance();
|
|
188
|
+
model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
189
|
+
}
|
|
190
|
+
// Build the image scalar texture
|
|
191
|
+
const dims = image.getDimensions();
|
|
192
|
+
// Use norm16 for the 3D texture if the extension is available
|
|
193
|
+
model.openGLTexture.setOglNorm16Ext(model.context.getExtension('EXT_texture_norm16'));
|
|
194
|
+
model.openGLTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
195
|
+
model.openGLTexture.resetFormatAndType();
|
|
196
|
+
model.openGLTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars);
|
|
197
|
+
model.openGLTextureString = toString;
|
|
198
|
+
if (scalars) {
|
|
199
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.openGLTexture, model.openGLTextureString);
|
|
196
200
|
}
|
|
201
|
+
} else {
|
|
202
|
+
model.openGLTexture = tex.vtkObj;
|
|
203
|
+
model.openGLTextureString = tex.hash;
|
|
197
204
|
}
|
|
198
205
|
const ppty = actor.getProperty();
|
|
199
206
|
const iComps = ppty.getIndependentComponents();
|
|
200
207
|
const numIComps = iComps ? numComp : 1;
|
|
201
208
|
const textureHeight = iComps ? 2 * numIComps : 1;
|
|
202
|
-
const
|
|
203
|
-
|
|
209
|
+
const colorTransferFunc = ppty.getRGBTransferFunction();
|
|
210
|
+
toString = computeFnToString(ppty, colorTransferFunc, numIComps);
|
|
211
|
+
const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
|
|
212
|
+
const reBuildC = !cTex?.vtkObj || cTex?.hash !== toString || model.colorTextureString !== toString;
|
|
213
|
+
if (reBuildC) {
|
|
204
214
|
const cWidth = 1024;
|
|
205
215
|
const cSize = cWidth * textureHeight * 3;
|
|
206
216
|
const cTable = new Uint8Array(cSize);
|
|
207
|
-
|
|
208
|
-
|
|
217
|
+
if (!model.colorTexture) {
|
|
218
|
+
model.colorTexture = vtkOpenGLTexture.newInstance();
|
|
219
|
+
model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
220
|
+
}
|
|
221
|
+
if (colorTransferFunc) {
|
|
209
222
|
const tmpTable = new Float32Array(cWidth * 3);
|
|
210
223
|
for (let c = 0; c < numIComps; c++) {
|
|
211
|
-
cfun = ppty.getRGBTransferFunction(c);
|
|
224
|
+
const cfun = ppty.getRGBTransferFunction(c);
|
|
212
225
|
const cRange = cfun.getRange();
|
|
213
226
|
cfun.getTable(cRange[0], cRange[1], cWidth, tmpTable, 1);
|
|
214
227
|
if (iComps) {
|
|
@@ -231,28 +244,40 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
231
244
|
cTable[i + 1] = 255.0 * i / ((cWidth - 1) * 3);
|
|
232
245
|
cTable[i + 2] = 255.0 * i / ((cWidth - 1) * 3);
|
|
233
246
|
}
|
|
247
|
+
model.colorTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
248
|
+
model.colorTexture.resetFormatAndType();
|
|
234
249
|
model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
235
250
|
}
|
|
236
|
-
model.colorTextureString =
|
|
251
|
+
model.colorTextureString = toString;
|
|
252
|
+
if (colorTransferFunc) {
|
|
253
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, model.colorTextureString);
|
|
254
|
+
}
|
|
255
|
+
} else {
|
|
256
|
+
model.colorTexture = cTex.vtkObj;
|
|
257
|
+
model.colorTextureString = cTex.hash;
|
|
237
258
|
}
|
|
238
259
|
|
|
239
260
|
// Build piecewise function buffer. This buffer is used either
|
|
240
261
|
// for component weighting or opacity, depending on whether we're
|
|
241
262
|
// rendering components independently or not.
|
|
242
|
-
const
|
|
243
|
-
|
|
263
|
+
const pwFunc = ppty.getPiecewiseFunction();
|
|
264
|
+
toString = computeFnToString(ppty, pwFunc, numIComps);
|
|
265
|
+
const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
|
|
266
|
+
// rebuild opacity tfun?
|
|
267
|
+
const reBuildPwf = !pwfTex?.vtkObj || pwfTex?.hash !== toString || model.pwfTextureString !== toString;
|
|
268
|
+
if (reBuildPwf) {
|
|
244
269
|
const pwfWidth = 1024;
|
|
245
270
|
const pwfSize = pwfWidth * textureHeight;
|
|
246
271
|
const pwfTable = new Uint8Array(pwfSize);
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
if (
|
|
272
|
+
if (!model.pwfTexture) {
|
|
273
|
+
model.pwfTexture = vtkOpenGLTexture.newInstance();
|
|
274
|
+
model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
275
|
+
}
|
|
276
|
+
if (pwFunc) {
|
|
252
277
|
const pwfFloatTable = new Float32Array(pwfSize);
|
|
253
278
|
const tmpTable = new Float32Array(pwfWidth);
|
|
254
279
|
for (let c = 0; c < numIComps; ++c) {
|
|
255
|
-
pwfun = ppty.getPiecewiseFunction(c);
|
|
280
|
+
const pwfun = ppty.getPiecewiseFunction(c);
|
|
256
281
|
if (pwfun === null) {
|
|
257
282
|
// Piecewise constant max if no function supplied for this component
|
|
258
283
|
pwfFloatTable.fill(1.0);
|
|
@@ -272,13 +297,23 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
272
297
|
}
|
|
273
298
|
}
|
|
274
299
|
}
|
|
300
|
+
model.pwfTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
301
|
+
model.pwfTexture.resetFormatAndType();
|
|
275
302
|
model.pwfTexture.create2DFromRaw(pwfWidth, textureHeight, 1, VtkDataTypes.FLOAT, pwfFloatTable);
|
|
276
303
|
} else {
|
|
277
304
|
// default is opaque
|
|
278
305
|
pwfTable.fill(255.0);
|
|
306
|
+
model.pwfTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
307
|
+
model.pwfTexture.resetFormatAndType();
|
|
279
308
|
model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable);
|
|
280
309
|
}
|
|
281
|
-
model.pwfTextureString =
|
|
310
|
+
model.pwfTextureString = toString;
|
|
311
|
+
if (pwFunc) {
|
|
312
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(pwFunc, model.pwfTexture, model.pwfTextureString);
|
|
313
|
+
}
|
|
314
|
+
} else {
|
|
315
|
+
model.pwfTexture = pwfTex.vtkObj;
|
|
316
|
+
model.pwfTextureString = pwfTex.hash;
|
|
282
317
|
}
|
|
283
318
|
const vboString = `${model.resliceGeom.getMTime()}A${model.renderable.getSlabThickness()}`;
|
|
284
319
|
if (!model.tris.getCABO().getElementCount() || model.VBOBuildString !== vboString) {
|
|
@@ -510,7 +545,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
510
545
|
if (!model.currentRenderPass && model.lastRenderPassShaderReplacement || model.currentRenderPass && model.currentRenderPass.getShaderReplacement() !== model.lastRenderPassShaderReplacement) {
|
|
511
546
|
needRebuild = true;
|
|
512
547
|
}
|
|
513
|
-
if (needRebuild || model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || cellBO.getProgram() === 0 || model.lastTextureComponents !== tNumComp || model.lastIndependentComponents !== iComp || model.lastSlabThickness !== slabTh || model.lastSlabType !== slabType || model.lastSlabTrapezoidIntegration !== slabTrap) {
|
|
548
|
+
if (needRebuild || model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || cellBO.getProgram()?.getHandle() === 0 || model.lastTextureComponents !== tNumComp || model.lastIndependentComponents !== iComp || model.lastSlabThickness !== slabTh || model.lastSlabType !== slabType || model.lastSlabTrapezoidIntegration !== slabTrap) {
|
|
514
549
|
model.lastHaveSeenDepthRequest = model.haveSeenDepthRequest;
|
|
515
550
|
model.lastTextureComponents = tNumComp;
|
|
516
551
|
model.lastIndependentComponents = iComp;
|
|
@@ -846,7 +881,8 @@ const DEFAULT_VALUES = {
|
|
|
846
881
|
tris: null,
|
|
847
882
|
colorTexture: null,
|
|
848
883
|
pwfTexture: null,
|
|
849
|
-
_externalOpenGLTexture: false
|
|
884
|
+
_externalOpenGLTexture: false,
|
|
885
|
+
_scalars: null
|
|
850
886
|
};
|
|
851
887
|
|
|
852
888
|
// ----------------------------------------------------------------------------
|
|
@@ -860,9 +896,9 @@ function extend(publicAPI, model) {
|
|
|
860
896
|
vtkReplacementShaderMapper.implementReplaceShaderCoincidentOffset(publicAPI, model, initialValues);
|
|
861
897
|
vtkReplacementShaderMapper.implementBuildShadersWithReplacements(publicAPI, model, initialValues);
|
|
862
898
|
model.tris = vtkHelper.newInstance();
|
|
863
|
-
model.openGLTexture =
|
|
864
|
-
model.colorTexture =
|
|
865
|
-
model.pwfTexture =
|
|
899
|
+
model.openGLTexture = null;
|
|
900
|
+
model.colorTexture = null;
|
|
901
|
+
model.pwfTexture = null;
|
|
866
902
|
model.VBOBuildTime = {};
|
|
867
903
|
obj(model.VBOBuildTime);
|
|
868
904
|
model.tmpMat4 = mat4.identity(new Float64Array(16));
|
|
@@ -1089,6 +1089,14 @@ function vtkOpenGLPolyDataMapper(publicAPI, model) {
|
|
|
1089
1089
|
model.VBOBuildString = toString;
|
|
1090
1090
|
}
|
|
1091
1091
|
};
|
|
1092
|
+
publicAPI.getAllocatedGPUMemoryInBytes = () => {
|
|
1093
|
+
let memUsed = 0;
|
|
1094
|
+
model.primitives.forEach(prim => {
|
|
1095
|
+
memUsed += prim.getAllocatedGPUMemoryInBytes();
|
|
1096
|
+
});
|
|
1097
|
+
// Return in MB
|
|
1098
|
+
return memUsed;
|
|
1099
|
+
};
|
|
1092
1100
|
}
|
|
1093
1101
|
|
|
1094
1102
|
// ----------------------------------------------------------------------------
|
|
@@ -406,6 +406,14 @@ function vtkOpenGLPolyDataMapper2D(publicAPI, model) {
|
|
|
406
406
|
mat4.transpose(tmpMat4, tmpMat4);
|
|
407
407
|
program.setUniformMatrix('WCVCMatrix', safeMatrixMultiply([tmpMat4, inverseShiftScaleMatrix], mat4, model.tmpMat4));
|
|
408
408
|
};
|
|
409
|
+
publicAPI.getAllocatedGPUMemoryInBytes = () => {
|
|
410
|
+
let memUsed = 0;
|
|
411
|
+
model.primitives.forEach(prim => {
|
|
412
|
+
memUsed += prim.getAllocatedGPUMemoryInBytes();
|
|
413
|
+
});
|
|
414
|
+
// Return in MB
|
|
415
|
+
return memUsed;
|
|
416
|
+
};
|
|
409
417
|
}
|
|
410
418
|
|
|
411
419
|
// ----------------------------------------------------------------------------
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { vtkAlgorithm, vtkObject } from './../../interfaces';
|
|
2
1
|
import { Nullable, Size, Vector2, Vector3 } from './../../types';
|
|
3
2
|
import { VtkDataTypes } from './../../Common/Core/DataArray';
|
|
3
|
+
import { vtkAlgorithm, vtkObject } from './../../interfaces';
|
|
4
|
+
import vtkBufferObject from './BufferObject';
|
|
5
|
+
import vtkCellArray from './../../Common/Core/CellArray';
|
|
6
|
+
import vtkDataArray from './../../Common/Core/DataArray';
|
|
7
|
+
import vtkOpenGLTexture from './Texture';
|
|
8
|
+
import vtkPoints from './../../Common/Core/Points';
|
|
4
9
|
import vtkRenderer from './../Core/Renderer';
|
|
5
10
|
import vtkTexture from './../Core/Texture';
|
|
6
11
|
import vtkViewStream from './../../IO/Core/ImageStream/ViewStream';
|
|
@@ -389,6 +394,37 @@ export interface vtkOpenGLRenderWindow extends vtkOpenGLRenderWindowBase {
|
|
|
389
394
|
* @see getContainerSize()
|
|
390
395
|
*/
|
|
391
396
|
getComputedDevicePixelRatio(): number;
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Set graphics resources for vtk objects to be cached at the context level.
|
|
400
|
+
* This provides mappers with a convenient API to re-use allocated GPU resources
|
|
401
|
+
* without duplication.
|
|
402
|
+
*
|
|
403
|
+
* @param {Object} vtkObj VTK data object / array with resources on the GPU
|
|
404
|
+
* @param {Object} gObj Container object that maintains a handle to the graphics resource on the GPU
|
|
405
|
+
* @param {String} hash String hash that can be used by mappers to decide whether to discard or re-allocate
|
|
406
|
+
* the cached resource.
|
|
407
|
+
*/
|
|
408
|
+
setGraphicsResourceForObject(vtkObj: vtkCellArray | vtkDataArray | vtkPoints, gObj: vtkOpenGLTexture | vtkBufferObject, hash: string): void;
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Get graphics resources for vtk objects cached at the context level.
|
|
412
|
+
* This provides mappers with a convenient API to re-use allocated GPU resources
|
|
413
|
+
* without duplication.
|
|
414
|
+
*
|
|
415
|
+
* @param {Object} vtkObj VTK data object / array with resources on the GPU
|
|
416
|
+
* the cached resource.
|
|
417
|
+
* @return {Object} Dictionary with the graphics resource and string hash
|
|
418
|
+
*/
|
|
419
|
+
getGraphicsResourceForObject(vtkObj: vtkCellArray | vtkDataArray | vtkPoints): {gObj: vtkOpenGLTexture | vtkBufferObject, hash: string};
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Get approximate graphics memory usage, in bytes, for the context. This is a simple computation
|
|
423
|
+
* that analyzes how much memory is allocated on the GPU for textures, VBOs, etc. to give an
|
|
424
|
+
* application a view of its graphics memory consumption.
|
|
425
|
+
* Note that this ignores page resources.
|
|
426
|
+
*/
|
|
427
|
+
getGraphicsMemoryInfo(): number;
|
|
392
428
|
}
|
|
393
429
|
|
|
394
430
|
/**
|
|
@@ -424,6 +424,31 @@ function vtkOpenGLRenderWindow(publicAPI, model) {
|
|
|
424
424
|
}
|
|
425
425
|
return -1;
|
|
426
426
|
};
|
|
427
|
+
publicAPI.getDefaultTextureByteSize = function (vtkType) {
|
|
428
|
+
let oglNorm16Ext = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
429
|
+
let useHalfFloat = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
430
|
+
if (model.webgl2) {
|
|
431
|
+
switch (vtkType) {
|
|
432
|
+
case VtkDataTypes.CHAR:
|
|
433
|
+
case VtkDataTypes.SIGNED_CHAR:
|
|
434
|
+
case VtkDataTypes.UNSIGNED_CHAR:
|
|
435
|
+
return 1;
|
|
436
|
+
case oglNorm16Ext:
|
|
437
|
+
case useHalfFloat:
|
|
438
|
+
case VtkDataTypes.UNSIGNED_SHORT:
|
|
439
|
+
case VtkDataTypes.SHORT:
|
|
440
|
+
case VtkDataTypes.VOID:
|
|
441
|
+
// Used for unsigned int depth
|
|
442
|
+
return 2;
|
|
443
|
+
default:
|
|
444
|
+
// For all other cases, assume float
|
|
445
|
+
return 4;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// webgl1 type support is limited to 1 byte
|
|
450
|
+
return 1;
|
|
451
|
+
};
|
|
427
452
|
publicAPI.getDefaultTextureInternalFormat = function (vtktype, numComps) {
|
|
428
453
|
let oglNorm16Ext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
|
429
454
|
let useHalfFloat = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
@@ -658,6 +683,9 @@ function vtkOpenGLRenderWindow(publicAPI, model) {
|
|
|
658
683
|
return lineWidthRange[1];
|
|
659
684
|
};
|
|
660
685
|
publicAPI.getGLInformations = () => {
|
|
686
|
+
if (model._glInformation) {
|
|
687
|
+
return model._glInformation;
|
|
688
|
+
}
|
|
661
689
|
const gl = publicAPI.get3DContext();
|
|
662
690
|
const glTextureFloat = gl.getExtension('OES_texture_float');
|
|
663
691
|
const glTextureHalfFloat = gl.getExtension('OES_texture_half_float');
|
|
@@ -675,6 +703,7 @@ function vtkOpenGLRenderWindow(publicAPI, model) {
|
|
|
675
703
|
};
|
|
676
704
|
}
|
|
677
705
|
}
|
|
706
|
+
model._glInformation = result;
|
|
678
707
|
return result;
|
|
679
708
|
};
|
|
680
709
|
publicAPI.traverseAllPasses = () => {
|
|
@@ -751,6 +780,58 @@ function vtkOpenGLRenderWindow(publicAPI, model) {
|
|
|
751
780
|
}
|
|
752
781
|
return modified;
|
|
753
782
|
};
|
|
783
|
+
publicAPI.getGraphicsResourceForObject = vtkObj => {
|
|
784
|
+
if (!vtkObj) {
|
|
785
|
+
return null;
|
|
786
|
+
}
|
|
787
|
+
const vtko = model._graphicsResources.get(vtkObj);
|
|
788
|
+
const vtkh = model._graphicsResourceHash.get(vtkObj);
|
|
789
|
+
return {
|
|
790
|
+
vtkObj: vtko,
|
|
791
|
+
hash: vtkh
|
|
792
|
+
};
|
|
793
|
+
};
|
|
794
|
+
publicAPI.setGraphicsResourceForObject = (vtkObj, gObj, hash) => {
|
|
795
|
+
if (!vtkObj) {
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
model._graphicsResources.set(vtkObj, gObj);
|
|
799
|
+
model._graphicsResourceHash.set(vtkObj, hash);
|
|
800
|
+
};
|
|
801
|
+
publicAPI.getGraphicsMemoryInfo = () => {
|
|
802
|
+
let memUsed = 0;
|
|
803
|
+
model._graphicsResources.forEach((gObj, vtkObj) => {
|
|
804
|
+
memUsed += gObj.getAllocatedGPUMemoryInBytes();
|
|
805
|
+
});
|
|
806
|
+
return memUsed;
|
|
807
|
+
};
|
|
808
|
+
publicAPI.releaseGraphicsResourcesForObject = vtkObj => {
|
|
809
|
+
if (!vtkObj) {
|
|
810
|
+
return false;
|
|
811
|
+
}
|
|
812
|
+
model._graphicsResources.get(vtkObj)?.releaseGraphicsResources(publicAPI);
|
|
813
|
+
return model._graphicsResources.delete(vtkObj) && model._graphicsResourceHash.delete(vtkObj);
|
|
814
|
+
};
|
|
815
|
+
publicAPI.releaseGraphicsResources = () => {
|
|
816
|
+
// Clear the shader cache
|
|
817
|
+
if (model.shaderCache !== null) {
|
|
818
|
+
model.shaderCache.releaseGraphicsResources(publicAPI);
|
|
819
|
+
}
|
|
820
|
+
// Free cached graphics resources at the context level
|
|
821
|
+
model._graphicsResources.forEach((gObj, vtkObj) => {
|
|
822
|
+
gObj.releaseGraphicsResources(publicAPI);
|
|
823
|
+
});
|
|
824
|
+
model._graphicsResources.clear();
|
|
825
|
+
model._graphicsResourceHash.clear();
|
|
826
|
+
if (model.textureUnitManager !== null) {
|
|
827
|
+
model.textureUnitManager.freeAll();
|
|
828
|
+
}
|
|
829
|
+
// Finally, ask the renderers to release prop resources
|
|
830
|
+
model.renderable.getRenderersByReference().forEach(ren => {
|
|
831
|
+
const glRen = publicAPI.getViewNodeFor(ren);
|
|
832
|
+
glRen?.releaseGraphicsResources();
|
|
833
|
+
});
|
|
834
|
+
};
|
|
754
835
|
}
|
|
755
836
|
|
|
756
837
|
// ----------------------------------------------------------------------------
|
|
@@ -809,6 +890,9 @@ function extend(publicAPI, model) {
|
|
|
809
890
|
model.bgImage.style.height = '100%';
|
|
810
891
|
model.bgImage.style.zIndex = '-1';
|
|
811
892
|
model._textureResourceIds = new Map();
|
|
893
|
+
model._graphicsResources = new Map();
|
|
894
|
+
model._graphicsResourceHash = new Map();
|
|
895
|
+
model._glInformation = null;
|
|
812
896
|
model.myFactory = vtkViewNodeFactory.newInstance();
|
|
813
897
|
/* eslint-disable no-use-before-define */
|
|
814
898
|
model.myFactory.registerOverride('vtkRenderWindow', newInstance);
|
|
@@ -148,6 +148,12 @@ function vtkOpenGLRenderer(publicAPI, model) {
|
|
|
148
148
|
if (model.selector !== null) {
|
|
149
149
|
model.selector.releaseGraphicsResources();
|
|
150
150
|
}
|
|
151
|
+
// Releasing resources means that the next render should re-create resources
|
|
152
|
+
if (model.renderable) {
|
|
153
|
+
model.renderable.getViewProps().forEach(prop => {
|
|
154
|
+
prop.modified();
|
|
155
|
+
});
|
|
156
|
+
}
|
|
151
157
|
};
|
|
152
158
|
publicAPI.setOpenGLRenderWindow = rw => {
|
|
153
159
|
if (model._openGLRenderWindow === rw) {
|
|
@@ -168,7 +174,7 @@ function vtkOpenGLRenderer(publicAPI, model) {
|
|
|
168
174
|
|
|
169
175
|
const DEFAULT_VALUES = {
|
|
170
176
|
context: null,
|
|
171
|
-
|
|
177
|
+
_openGLRenderWindow: null,
|
|
172
178
|
selector: null
|
|
173
179
|
};
|
|
174
180
|
|
|
@@ -4,7 +4,7 @@ import vtkShaderProgram from './ShaderProgram.js';
|
|
|
4
4
|
|
|
5
5
|
// ----------------------------------------------------------------------------
|
|
6
6
|
|
|
7
|
-
const SET_GET_FIELDS = ['
|
|
7
|
+
const SET_GET_FIELDS = ['lastShaderProgramBound', 'context', '_openGLRenderWindow'];
|
|
8
8
|
|
|
9
9
|
// ----------------------------------------------------------------------------
|
|
10
10
|
// vtkShaderCache methods
|
|
@@ -67,24 +67,24 @@ function vtkShaderCache(publicAPI, model) {
|
|
|
67
67
|
// return NULL if there is an issue
|
|
68
68
|
publicAPI.readyShaderProgramArray = (vertexCode, fragmentCode, geometryCode) => {
|
|
69
69
|
const data = publicAPI.replaceShaderValues(vertexCode, fragmentCode, geometryCode);
|
|
70
|
-
const
|
|
71
|
-
return publicAPI.readyShaderProgram(
|
|
70
|
+
const shaderProgram = publicAPI.getShaderProgram(data.VSSource, data.FSSource, data.GSSource);
|
|
71
|
+
return publicAPI.readyShaderProgram(shaderProgram);
|
|
72
72
|
};
|
|
73
|
-
publicAPI.readyShaderProgram =
|
|
74
|
-
if (!
|
|
73
|
+
publicAPI.readyShaderProgram = program => {
|
|
74
|
+
if (!program) {
|
|
75
75
|
return null;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// compile if needed
|
|
79
|
-
if (!
|
|
79
|
+
if (!program.getCompiled() && !program.compileShader()) {
|
|
80
80
|
return null;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
// bind if needed
|
|
84
|
-
if (!publicAPI.
|
|
84
|
+
if (!publicAPI.bindShaderProgram(program)) {
|
|
85
85
|
return null;
|
|
86
86
|
}
|
|
87
|
-
return
|
|
87
|
+
return program;
|
|
88
88
|
};
|
|
89
89
|
publicAPI.getShaderProgram = (vertexCode, fragmentCode, geometryCode) => {
|
|
90
90
|
// compute the MD5 and the check the map
|
|
@@ -116,27 +116,28 @@ function vtkShaderCache(publicAPI, model) {
|
|
|
116
116
|
// have to loop over all the programs were in use and invoke
|
|
117
117
|
// release graphics resources individually.
|
|
118
118
|
|
|
119
|
-
publicAPI.
|
|
120
|
-
Object.keys(model.shaderPrograms).map(key => model.shaderPrograms[key]).forEach(sp => sp.
|
|
119
|
+
publicAPI.releaseCurrentShaderProgram();
|
|
120
|
+
Object.keys(model.shaderPrograms).map(key => model.shaderPrograms[key]).forEach(sp => sp.cleanup());
|
|
121
|
+
model.shaderPrograms = {};
|
|
121
122
|
};
|
|
122
|
-
publicAPI.
|
|
123
|
+
publicAPI.releaseCurrentShaderProgram = () => {
|
|
123
124
|
// release prior shader
|
|
124
|
-
if (model.
|
|
125
|
-
model.
|
|
126
|
-
model.
|
|
125
|
+
if (model.lastShaderProgramBound) {
|
|
126
|
+
model.lastShaderProgramBound.cleanup();
|
|
127
|
+
model.lastShaderProgramBound = null;
|
|
127
128
|
}
|
|
128
129
|
};
|
|
129
|
-
publicAPI.
|
|
130
|
-
if (model.
|
|
130
|
+
publicAPI.bindShaderProgram = program => {
|
|
131
|
+
if (model.lastShaderProgramBound === program) {
|
|
131
132
|
return 1;
|
|
132
133
|
}
|
|
133
134
|
|
|
134
|
-
// release prior
|
|
135
|
-
if (model.
|
|
136
|
-
model.
|
|
135
|
+
// release prior program
|
|
136
|
+
if (model.lastShaderProgramBound) {
|
|
137
|
+
model.lastShaderProgramBound.release();
|
|
137
138
|
}
|
|
138
|
-
|
|
139
|
-
model.
|
|
139
|
+
program.bind();
|
|
140
|
+
model.lastShaderProgramBound = program;
|
|
140
141
|
return 1;
|
|
141
142
|
};
|
|
142
143
|
}
|
|
@@ -146,7 +147,7 @@ function vtkShaderCache(publicAPI, model) {
|
|
|
146
147
|
// ----------------------------------------------------------------------------
|
|
147
148
|
|
|
148
149
|
const DEFAULT_VALUES = {
|
|
149
|
-
|
|
150
|
+
lastShaderProgramBound: null,
|
|
150
151
|
shaderPrograms: null,
|
|
151
152
|
context: null
|
|
152
153
|
// _openGLRenderWindow: null,
|
|
@@ -64,8 +64,18 @@ function vtkShaderProgram(publicAPI, model) {
|
|
|
64
64
|
if (model.shaderType === 'Unknown' || model.handle === 0) {
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
publicAPI.release();
|
|
68
|
+
if (model.vertexShaderHandle !== 0) {
|
|
69
|
+
model.context.detachShader(model.handle, model.vertexShaderHandle);
|
|
70
|
+
model.vertexShaderHandle = 0;
|
|
71
|
+
}
|
|
72
|
+
if (model.fragmentShaderHandle !== 0) {
|
|
73
|
+
model.context.detachShader(model.handle, model.fragmentShaderHandle);
|
|
74
|
+
model.fragmentShaderHandle = 0;
|
|
75
|
+
}
|
|
76
|
+
model.context.deleteProgram(model.handle);
|
|
68
77
|
model.handle = 0;
|
|
78
|
+
publicAPI.setCompiled(false);
|
|
69
79
|
};
|
|
70
80
|
publicAPI.bind = () => {
|
|
71
81
|
if (!model.linked && !publicAPI.link()) {
|
|
@@ -406,7 +416,7 @@ function vtkShaderProgram(publicAPI, model) {
|
|
|
406
416
|
}
|
|
407
417
|
if (shader.getShaderType() === 'Vertex') {
|
|
408
418
|
if (model.vertexShaderHandle !== 0) {
|
|
409
|
-
model.
|
|
419
|
+
model.context.detachShader(model.handle, model.vertexShaderHandle);
|
|
410
420
|
}
|
|
411
421
|
model.vertexShaderHandle = shader.getHandle();
|
|
412
422
|
}
|
|
@@ -212,6 +212,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
212
212
|
model.width = 0;
|
|
213
213
|
model.height = 0;
|
|
214
214
|
model.depth = 0;
|
|
215
|
+
model.allocatedGPUMemoryInBytes = 0;
|
|
215
216
|
}
|
|
216
217
|
if (model.shaderProgram) {
|
|
217
218
|
model.shaderProgram.releaseGraphicsResources(rwin);
|
|
@@ -701,6 +702,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
701
702
|
if (flip) {
|
|
702
703
|
model.context.pixelStorei(model.context.UNPACK_FLIP_Y_WEBGL, false);
|
|
703
704
|
}
|
|
705
|
+
model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, model.useHalfFloat);
|
|
704
706
|
publicAPI.deactivate();
|
|
705
707
|
return true;
|
|
706
708
|
};
|
|
@@ -778,7 +780,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
778
780
|
h /= 2;
|
|
779
781
|
}
|
|
780
782
|
}
|
|
781
|
-
|
|
783
|
+
model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, model.useHalfFloat);
|
|
782
784
|
// generateMipmap must not be called here because we manually upload all levels
|
|
783
785
|
// if it is called, all levels will be overwritten
|
|
784
786
|
|
|
@@ -828,6 +830,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
828
830
|
if (model.generateMipmap) {
|
|
829
831
|
model.context.generateMipmap(model.target);
|
|
830
832
|
}
|
|
833
|
+
model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, model.useHalfFloat);
|
|
831
834
|
publicAPI.deactivate();
|
|
832
835
|
return true;
|
|
833
836
|
};
|
|
@@ -877,6 +880,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
877
880
|
if (model.generateMipmap) {
|
|
878
881
|
model.context.generateMipmap(model.target);
|
|
879
882
|
}
|
|
883
|
+
model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(VtkDataTypes.UNSIGNED_CHAR, model.oglNorm16Ext, model.useHalfFloat);
|
|
880
884
|
publicAPI.deactivate();
|
|
881
885
|
return true;
|
|
882
886
|
};
|
|
@@ -1016,6 +1020,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1016
1020
|
if (model.generateMipmap) {
|
|
1017
1021
|
model.context.generateMipmap(model.target);
|
|
1018
1022
|
}
|
|
1023
|
+
model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, model.useHalfFloat);
|
|
1019
1024
|
publicAPI.deactivate();
|
|
1020
1025
|
return true;
|
|
1021
1026
|
};
|
|
@@ -1296,7 +1301,8 @@ const DEFAULT_VALUES = {
|
|
|
1296
1301
|
// the voxel intensity range is out of the accurate
|
|
1297
1302
|
// range of half float
|
|
1298
1303
|
useHalfFloat: true,
|
|
1299
|
-
oglNorm16Ext: null
|
|
1304
|
+
oglNorm16Ext: null,
|
|
1305
|
+
allocatedGPUMemoryInBytes: 0
|
|
1300
1306
|
};
|
|
1301
1307
|
|
|
1302
1308
|
// ----------------------------------------------------------------------------
|
|
@@ -1319,7 +1325,7 @@ function extend(publicAPI, model) {
|
|
|
1319
1325
|
// Build VTK API
|
|
1320
1326
|
set(publicAPI, model, ['format', 'openGLDataType']);
|
|
1321
1327
|
setGet(publicAPI, model, ['keyMatrixTime', 'minificationFilter', 'magnificationFilter', 'wrapS', 'wrapT', 'wrapR', 'generateMipmap', 'oglNorm16Ext']);
|
|
1322
|
-
get(publicAPI, model, ['width', 'height', 'volumeInfo', 'components', 'handle', 'target']);
|
|
1328
|
+
get(publicAPI, model, ['width', 'height', 'volumeInfo', 'components', 'handle', 'target', 'allocatedGPUMemoryInBytes']);
|
|
1323
1329
|
moveToProtected(publicAPI, model, ['openGLRenderWindow']);
|
|
1324
1330
|
|
|
1325
1331
|
// Object methods
|
|
@@ -81,6 +81,11 @@ function vtkOpenGLTextureUnitManager(publicAPI, model) {
|
|
|
81
81
|
publicAPI.free = val => {
|
|
82
82
|
model.textureUnits[val] = false;
|
|
83
83
|
};
|
|
84
|
+
publicAPI.freeAll = () => {
|
|
85
|
+
for (let i = 0; i < model.numberOfTextureUnits; ++i) {
|
|
86
|
+
model.textureUnits[i] = false;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
// ----------------------------------------------------------------------------
|
|
@@ -22,6 +22,9 @@ const {
|
|
|
22
22
|
vtkErrorMacro
|
|
23
23
|
} = macro;
|
|
24
24
|
|
|
25
|
+
// ----------------------------------------------------------------------------
|
|
26
|
+
// helper methods
|
|
27
|
+
// ----------------------------------------------------------------------------
|
|
25
28
|
// TODO: Do we want this in some shared utility? Shouldwe just use lodash.isEqual
|
|
26
29
|
function arrayEquals(a, b) {
|
|
27
30
|
if (a.length !== b.length) {
|
|
@@ -34,6 +37,13 @@ function arrayEquals(a, b) {
|
|
|
34
37
|
}
|
|
35
38
|
return true;
|
|
36
39
|
}
|
|
40
|
+
function computeFnToString(property, pwfun, numberOfComponents) {
|
|
41
|
+
if (pwfun) {
|
|
42
|
+
const iComps = property.getIndependentComponents();
|
|
43
|
+
return `${pwfun.getMTime()}-${iComps}-${numberOfComponents}`;
|
|
44
|
+
}
|
|
45
|
+
return '0';
|
|
46
|
+
}
|
|
37
47
|
|
|
38
48
|
// ----------------------------------------------------------------------------
|
|
39
49
|
// vtkOpenGLVolumeMapper methods
|
|
@@ -283,7 +293,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
283
293
|
}
|
|
284
294
|
|
|
285
295
|
// has something changed that would require us to recreate the shader?
|
|
286
|
-
if (cellBO.getProgram() === 0 || needRebuild || model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || !!model.lastZBufferTexture !== !!model.zBufferTexture || cellBO.getShaderSourceTime().getMTime() < publicAPI.getMTime() || cellBO.getShaderSourceTime().getMTime() < model.renderable.getMTime()) {
|
|
296
|
+
if (cellBO.getProgram()?.getHandle() === 0 || needRebuild || model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || !!model.lastZBufferTexture !== !!model.zBufferTexture || cellBO.getShaderSourceTime().getMTime() < publicAPI.getMTime() || cellBO.getShaderSourceTime().getMTime() < model.renderable.getMTime()) {
|
|
287
297
|
model.lastZBufferTexture = model.zBufferTexture;
|
|
288
298
|
return true;
|
|
289
299
|
}
|
|
@@ -944,6 +954,10 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
944
954
|
if (!scalars) {
|
|
945
955
|
return;
|
|
946
956
|
}
|
|
957
|
+
if (model._scalars !== scalars) {
|
|
958
|
+
model._openGLRenderWindow.releaseGraphicsResourcesForObject(model._scalars);
|
|
959
|
+
model._scalars = scalars;
|
|
960
|
+
}
|
|
947
961
|
const vprop = actor.getProperty();
|
|
948
962
|
if (!model.jitterTexture.getHandle()) {
|
|
949
963
|
const oTable = new Uint8Array(32 * 32);
|
|
@@ -957,10 +971,12 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
957
971
|
const numComp = scalars.getNumberOfComponents();
|
|
958
972
|
const iComps = vprop.getIndependentComponents();
|
|
959
973
|
const numIComps = iComps ? numComp : 1;
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
let toString =
|
|
963
|
-
|
|
974
|
+
const scalarOpacityFunc = vprop.getScalarOpacity();
|
|
975
|
+
const opTex = model._openGLRenderWindow.getGraphicsResourceForObject(scalarOpacityFunc);
|
|
976
|
+
let toString = computeFnToString(vprop, scalarOpacityFunc, numIComps);
|
|
977
|
+
const reBuildOp = !opTex.vtkObj || opTex.hash !== toString || model.opacityTextureString !== toString;
|
|
978
|
+
if (reBuildOp) {
|
|
979
|
+
// rebuild opacity tfun?
|
|
964
980
|
const oWidth = 1024;
|
|
965
981
|
const oSize = oWidth * 2 * numIComps;
|
|
966
982
|
const ofTable = new Float32Array(oSize);
|
|
@@ -977,6 +993,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
977
993
|
}
|
|
978
994
|
}
|
|
979
995
|
model.opacityTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
996
|
+
model.opacityTexture.resetFormatAndType();
|
|
980
997
|
model.opacityTexture.setMinificationFilter(Filter.LINEAR);
|
|
981
998
|
model.opacityTexture.setMagnificationFilter(Filter.LINEAR);
|
|
982
999
|
|
|
@@ -994,11 +1011,20 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
994
1011
|
model.opacityTexture.create2DFromRaw(oWidth, 2 * numIComps, 1, VtkDataTypes.UNSIGNED_CHAR, oTable);
|
|
995
1012
|
}
|
|
996
1013
|
model.opacityTextureString = toString;
|
|
1014
|
+
if (scalarOpacityFunc) {
|
|
1015
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(scalarOpacityFunc, model.opacityTexture, model.opacityTextureString);
|
|
1016
|
+
}
|
|
1017
|
+
} else {
|
|
1018
|
+
model.opacityTexture = opTex.vtkObj;
|
|
1019
|
+
model.opacityTextureString = opTex.hash;
|
|
997
1020
|
}
|
|
998
1021
|
|
|
999
1022
|
// rebuild color tfun?
|
|
1000
|
-
|
|
1001
|
-
|
|
1023
|
+
const colorTransferFunc = vprop.getRGBTransferFunction();
|
|
1024
|
+
toString = computeFnToString(vprop, colorTransferFunc, numIComps);
|
|
1025
|
+
const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
|
|
1026
|
+
const reBuildC = !cTex?.vtkObj || cTex?.hash !== toString || model.colorTextureString !== toString;
|
|
1027
|
+
if (reBuildC) {
|
|
1002
1028
|
const cWidth = 1024;
|
|
1003
1029
|
const cSize = cWidth * 2 * numIComps * 3;
|
|
1004
1030
|
const cTable = new Uint8Array(cSize);
|
|
@@ -1013,15 +1039,23 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
1013
1039
|
}
|
|
1014
1040
|
}
|
|
1015
1041
|
model.colorTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
1042
|
+
model.colorTexture.resetFormatAndType();
|
|
1016
1043
|
model.colorTexture.setMinificationFilter(Filter.LINEAR);
|
|
1017
1044
|
model.colorTexture.setMagnificationFilter(Filter.LINEAR);
|
|
1018
1045
|
model.colorTexture.create2DFromRaw(cWidth, 2 * numIComps, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
1019
1046
|
model.colorTextureString = toString;
|
|
1047
|
+
if (colorTransferFunc) {
|
|
1048
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, model.colorTextureString);
|
|
1049
|
+
}
|
|
1050
|
+
} else {
|
|
1051
|
+
model.colorTexture = cTex.vtkObj;
|
|
1052
|
+
model.colorTextureString = cTex.hash;
|
|
1020
1053
|
}
|
|
1021
|
-
|
|
1054
|
+
const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
|
|
1022
1055
|
// rebuild the scalarTexture if the data has changed
|
|
1023
|
-
toString = `${image.getMTime()}`;
|
|
1024
|
-
|
|
1056
|
+
toString = `${image.getMTime()}A${scalars.getMTime()}`;
|
|
1057
|
+
const reBuildTex = !tex?.vtkObj || tex?.hash !== toString || model.scalarTextureString !== toString;
|
|
1058
|
+
if (reBuildTex) {
|
|
1025
1059
|
// Build the textures
|
|
1026
1060
|
const dims = image.getDimensions();
|
|
1027
1061
|
// Use norm16 for scalar texture if the extension is available
|
|
@@ -1030,6 +1064,12 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
1030
1064
|
model.scalarTexture.resetFormatAndType();
|
|
1031
1065
|
model.scalarTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars, model.renderable.getPreferSizeOverAccuracy());
|
|
1032
1066
|
model.scalarTextureString = toString;
|
|
1067
|
+
if (scalars) {
|
|
1068
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.scalarTexture, model.scalarTextureString);
|
|
1069
|
+
}
|
|
1070
|
+
} else {
|
|
1071
|
+
model.scalarTexture = tex.vtkObj;
|
|
1072
|
+
model.scalarTextureString = tex.hash;
|
|
1033
1073
|
}
|
|
1034
1074
|
if (!model.tris.getCABO().getElementCount()) {
|
|
1035
1075
|
// build the CABO
|
|
@@ -1122,7 +1162,8 @@ const DEFAULT_VALUES = {
|
|
|
1122
1162
|
modelToView: null,
|
|
1123
1163
|
projectionToView: null,
|
|
1124
1164
|
avgWindowArea: 0.0,
|
|
1125
|
-
avgFrameTime: 0.0
|
|
1165
|
+
avgFrameTime: 0.0,
|
|
1166
|
+
_scalars: null
|
|
1126
1167
|
};
|
|
1127
1168
|
|
|
1128
1169
|
// ----------------------------------------------------------------------------
|