@kitware/vtk.js 26.9.13 → 27.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.
- package/Interaction/Style/InteractorStyleImage.d.ts +107 -0
- package/Interaction/Style/InteractorStyleImage.js +14 -0
- package/Interaction/Style/InteractorStyleTrackballCamera.d.ts +170 -0
- package/Rendering/Core/AbstractImageMapper.d.ts +3 -3
- package/Rendering/Core/AbstractImageMapper.js +5 -3
- package/Rendering/Core/AbstractMapper3D.js +9 -1
- package/Rendering/Core/ImageProperty/Constants.js +2 -2
- package/Rendering/Core/ImageProperty.js +2 -2
- package/Rendering/Core/ImageResliceMapper/Constants.d.ts +11 -0
- package/Rendering/Core/ImageResliceMapper/Constants.js +11 -0
- package/Rendering/Core/ImageResliceMapper.d.ts +245 -0
- package/Rendering/Core/ImageResliceMapper.js +70 -0
- package/Rendering/Core/Mapper.js +1 -7
- package/Rendering/Core.js +2 -0
- package/Rendering/OpenGL/ImageMapper.js +1 -11
- package/Rendering/OpenGL/ImageResliceMapper.js +996 -0
- package/Rendering/OpenGL/PolyDataMapper.js +4 -81
- package/Rendering/OpenGL/PolyDataMapper2D.js +4 -75
- package/Rendering/OpenGL/Profiles/All.js +1 -0
- package/Rendering/OpenGL/Profiles/Volume.js +1 -0
- package/Rendering/OpenGL/ReplacementShaderMapper.js +80 -1
- package/Rendering/OpenGL/ShaderProgram.js +1 -1
- package/Rendering/OpenGL/Texture.js +2 -2
- package/Rendering/OpenGL/glsl/vtkImageResliceMapperFS.glsl.js +3 -0
- package/Rendering/OpenGL/glsl/vtkImageResliceMapperVS.glsl.js +3 -0
- package/Rendering/OpenGL.js +3 -1
- package/Rendering/Profiles/All.js +1 -0
- package/Rendering/Profiles/Volume.js +1 -0
- package/index.d.ts +4 -0
- package/package.json +3 -3
|
@@ -0,0 +1,996 @@
|
|
|
1
|
+
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
2
|
+
import { newInstance as newInstance$1, obj, get, vtkErrorMacro as vtkErrorMacro$1 } from '../../macros.js';
|
|
3
|
+
import { mat4, vec3 } from 'gl-matrix';
|
|
4
|
+
import vtkClosedPolyLineToSurfaceFilter from '../../Filters/General/ClosedPolyLineToSurfaceFilter.js';
|
|
5
|
+
import vtkCubeSource from '../../Filters/Sources/CubeSource.js';
|
|
6
|
+
import vtkCutter from '../../Filters/Core/Cutter.js';
|
|
7
|
+
import vtkDataArray from '../../Common/Core/DataArray.js';
|
|
8
|
+
import vtkHelper from './Helper.js';
|
|
9
|
+
import { f as vtkMath } from '../../Common/Core/Math/index.js';
|
|
10
|
+
import vtkOpenGLTexture from './Texture.js';
|
|
11
|
+
import vtkPlane from '../../Common/DataModel/Plane.js';
|
|
12
|
+
import vtkPolyData from '../../Common/DataModel/PolyData.js';
|
|
13
|
+
import vtkReplacementShaderMapper from './ReplacementShaderMapper.js';
|
|
14
|
+
import vtkShaderProgram from './ShaderProgram.js';
|
|
15
|
+
import vtkViewNode from '../SceneGraph/ViewNode.js';
|
|
16
|
+
import { v as vtkImageResliceMapperVS } from './glsl/vtkImageResliceMapperVS.glsl.js';
|
|
17
|
+
import { v as vtkImageResliceMapperFS } from './glsl/vtkImageResliceMapperFS.glsl.js';
|
|
18
|
+
import InterpolationType from '../Core/ImageProperty/Constants.js';
|
|
19
|
+
import { VtkDataTypes } from '../../Common/Core/DataArray/Constants.js';
|
|
20
|
+
import { Filter } from './Texture/Constants.js';
|
|
21
|
+
import { Representation } from '../Core/Property/Constants.js';
|
|
22
|
+
import { registerOverride } from './ViewNodeFactory.js';
|
|
23
|
+
|
|
24
|
+
var vtkErrorMacro = vtkErrorMacro$1; // ----------------------------------------------------------------------------
|
|
25
|
+
// helper methods
|
|
26
|
+
// ----------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
function computeFnToString(property, fn, numberOfComponents) {
|
|
29
|
+
var pwfun = fn.apply(property);
|
|
30
|
+
|
|
31
|
+
if (pwfun) {
|
|
32
|
+
var iComps = property.getIndependentComponents();
|
|
33
|
+
return "".concat(property.getMTime(), "-").concat(iComps, "-").concat(numberOfComponents);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return '0';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function safeMatrixMultiply(matrixArray, matrixType, tmpMat) {
|
|
40
|
+
matrixType.identity(tmpMat);
|
|
41
|
+
return matrixArray.reduce(function (res, matrix, index) {
|
|
42
|
+
if (index === 0) {
|
|
43
|
+
return matrix ? matrixType.copy(res, matrix) : matrixType.identity(res);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return matrix ? matrixType.multiply(res, res, matrix) : res;
|
|
47
|
+
}, tmpMat);
|
|
48
|
+
} // ----------------------------------------------------------------------------
|
|
49
|
+
// vtkOpenGLImageResliceMapper methods
|
|
50
|
+
// ----------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
54
|
+
// Set our className
|
|
55
|
+
model.classHierarchy.push('vtkOpenGLImageResliceMapper');
|
|
56
|
+
|
|
57
|
+
publicAPI.buildPass = function (prepass) {
|
|
58
|
+
if (prepass) {
|
|
59
|
+
model.currentRenderPass = null;
|
|
60
|
+
model._openGLImageSlice = publicAPI.getFirstAncestorOfType('vtkOpenGLImageSlice');
|
|
61
|
+
model._openGLRenderer = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderer');
|
|
62
|
+
|
|
63
|
+
var ren = model._openGLRenderer.getRenderable();
|
|
64
|
+
|
|
65
|
+
model._openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera());
|
|
66
|
+
model._openGLRenderWindow = model._openGLRenderer.getParent();
|
|
67
|
+
model.context = model._openGLRenderWindow.getContext();
|
|
68
|
+
model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
69
|
+
|
|
70
|
+
if (!model.openGLTexture) {
|
|
71
|
+
model.openGLTexture = vtkOpenGLTexture.newInstance();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
75
|
+
model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
76
|
+
model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
publicAPI.translucentPass = function (prepass, renderPass) {
|
|
81
|
+
if (prepass) {
|
|
82
|
+
model.currentRenderPass = renderPass;
|
|
83
|
+
publicAPI.render();
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
publicAPI.zBufferPass = function (prepass) {
|
|
88
|
+
if (prepass) {
|
|
89
|
+
model.haveSeenDepthRequest = true;
|
|
90
|
+
model.renderDepth = true;
|
|
91
|
+
publicAPI.render();
|
|
92
|
+
model.renderDepth = false;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
publicAPI.opaqueZBufferPass = function (prepass) {
|
|
97
|
+
return publicAPI.zBufferPass(prepass);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
publicAPI.opaquePass = function (prepass) {
|
|
101
|
+
if (prepass) {
|
|
102
|
+
publicAPI.render();
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
publicAPI.getCoincidentParameters = function (ren, actor) {
|
|
107
|
+
if (model.renderable.getResolveCoincidentTopology()) {
|
|
108
|
+
return model.renderable.getCoincidentTopologyPolygonOffsetParameters();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return null;
|
|
112
|
+
}; // Renders myself
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
publicAPI.render = function () {
|
|
116
|
+
var actor = model._openGLImageSlice.getRenderable();
|
|
117
|
+
|
|
118
|
+
var ren = model._openGLRenderer.getRenderable();
|
|
119
|
+
|
|
120
|
+
publicAPI.renderPiece(ren, actor);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
publicAPI.renderPiece = function (ren, actor) {
|
|
124
|
+
publicAPI.invokeEvent({
|
|
125
|
+
type: 'StartEvent'
|
|
126
|
+
});
|
|
127
|
+
model.renderable.update();
|
|
128
|
+
model.currentInput = model.renderable.getInputData();
|
|
129
|
+
publicAPI.invokeEvent({
|
|
130
|
+
type: 'EndEvent'
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
if (!model.currentInput) {
|
|
134
|
+
vtkErrorMacro('No input!');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
publicAPI.updateResliceGeometry();
|
|
139
|
+
publicAPI.renderPieceStart(ren, actor);
|
|
140
|
+
publicAPI.renderPieceDraw(ren, actor);
|
|
141
|
+
publicAPI.renderPieceFinish(ren, actor);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
publicAPI.renderPieceStart = function (ren, actor) {
|
|
145
|
+
// make sure the BOs are up to date
|
|
146
|
+
publicAPI.updateBufferObjects(ren, actor);
|
|
147
|
+
var iType = actor.getProperty().getInterpolationType();
|
|
148
|
+
|
|
149
|
+
if (iType === InterpolationType.NEAREST) {
|
|
150
|
+
model.openGLTexture.setMinificationFilter(Filter.NEAREST);
|
|
151
|
+
model.openGLTexture.setMagnificationFilter(Filter.NEAREST);
|
|
152
|
+
model.colorTexture.setMinificationFilter(Filter.NEAREST);
|
|
153
|
+
model.colorTexture.setMagnificationFilter(Filter.NEAREST);
|
|
154
|
+
model.pwfTexture.setMinificationFilter(Filter.NEAREST);
|
|
155
|
+
model.pwfTexture.setMagnificationFilter(Filter.NEAREST);
|
|
156
|
+
} else {
|
|
157
|
+
model.openGLTexture.setMinificationFilter(Filter.LINEAR);
|
|
158
|
+
model.openGLTexture.setMagnificationFilter(Filter.LINEAR);
|
|
159
|
+
model.colorTexture.setMinificationFilter(Filter.LINEAR);
|
|
160
|
+
model.colorTexture.setMagnificationFilter(Filter.LINEAR);
|
|
161
|
+
model.pwfTexture.setMinificationFilter(Filter.LINEAR);
|
|
162
|
+
model.pwfTexture.setMagnificationFilter(Filter.LINEAR);
|
|
163
|
+
} // No buffer objects bound.
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
model.lastBoundBO = null;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
publicAPI.renderPieceDraw = function (ren, actor) {
|
|
170
|
+
var gl = model.context; // render the texture
|
|
171
|
+
|
|
172
|
+
model.openGLTexture.activate();
|
|
173
|
+
model.colorTexture.activate();
|
|
174
|
+
model.pwfTexture.activate(); // update shaders if required
|
|
175
|
+
|
|
176
|
+
publicAPI.updateShaders(model.tris, ren, actor); // Finally draw
|
|
177
|
+
|
|
178
|
+
gl.drawArrays(gl.TRIANGLES, 0, model.tris.getCABO().getElementCount());
|
|
179
|
+
model.tris.getVAO().release();
|
|
180
|
+
model.openGLTexture.deactivate();
|
|
181
|
+
model.colorTexture.deactivate();
|
|
182
|
+
model.pwfTexture.deactivate();
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
publicAPI.renderPieceFinish = function (ren, actor) {};
|
|
186
|
+
|
|
187
|
+
publicAPI.updateBufferObjects = function (ren, actor) {
|
|
188
|
+
// Rebuild buffer objects if needed
|
|
189
|
+
if (publicAPI.getNeedToRebuildBufferObjects(ren, actor)) {
|
|
190
|
+
publicAPI.buildBufferObjects(ren, actor);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
publicAPI.getNeedToRebuildBufferObjects = function (ren, actor) {
|
|
195
|
+
return model.VBOBuildTime.getMTime() < publicAPI.getMTime() || model.VBOBuildTime.getMTime() < actor.getMTime() || model.VBOBuildTime.getMTime() < model.renderable.getMTime() || model.VBOBuildTime.getMTime() < actor.getProperty().getMTime() || model.VBOBuildTime.getMTime() < model.currentInput.getMTime() || model.VBOBuildTime.getMTime() < model.resliceGeom.getMTime();
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
publicAPI.buildBufferObjects = function (ren, actor) {
|
|
199
|
+
var _image$getPointData;
|
|
200
|
+
|
|
201
|
+
var image = model.currentInput;
|
|
202
|
+
|
|
203
|
+
if (!image) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
var scalars = (_image$getPointData = image.getPointData()) === null || _image$getPointData === void 0 ? void 0 : _image$getPointData.getScalars();
|
|
208
|
+
|
|
209
|
+
if (!scalars) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
var numComp = scalars.getNumberOfComponents();
|
|
214
|
+
|
|
215
|
+
if (!model._externalOpenGLTexture) {
|
|
216
|
+
var _toString = "".concat(image.getMTime(), "A").concat(scalars.getMTime());
|
|
217
|
+
|
|
218
|
+
if (model.openGLTextureString !== _toString) {
|
|
219
|
+
// Build the image scalar texture
|
|
220
|
+
var dims = image.getDimensions(); // Use norm16 for the 3D texture if the extension is available
|
|
221
|
+
|
|
222
|
+
model.openGLTexture.getOglNorm16Ext(model.context.getExtension('EXT_texture_norm16'));
|
|
223
|
+
model.openGLTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
224
|
+
model.openGLTexture.resetFormatAndType();
|
|
225
|
+
model.openGLTexture.create3DFilterableFromRaw(dims[0], dims[1], dims[2], numComp, scalars.getDataType(), scalars.getData());
|
|
226
|
+
model.openGLTextureString = _toString;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
var ppty = actor.getProperty();
|
|
231
|
+
var iComps = ppty.getIndependentComponents();
|
|
232
|
+
var numIComps = iComps ? numComp : 1;
|
|
233
|
+
var textureHeight = iComps ? 2 * numIComps : 1;
|
|
234
|
+
var cfunToString = computeFnToString(ppty, ppty.getRGBTransferFunction, numIComps);
|
|
235
|
+
|
|
236
|
+
if (model.colorTextureString !== cfunToString) {
|
|
237
|
+
var cWidth = 1024;
|
|
238
|
+
var cSize = cWidth * textureHeight * 3;
|
|
239
|
+
var cTable = new Uint8Array(cSize);
|
|
240
|
+
var cfun = ppty.getRGBTransferFunction();
|
|
241
|
+
|
|
242
|
+
if (cfun) {
|
|
243
|
+
var tmpTable = new Float32Array(cWidth * 3);
|
|
244
|
+
|
|
245
|
+
for (var c = 0; c < numIComps; c++) {
|
|
246
|
+
cfun = ppty.getRGBTransferFunction(c);
|
|
247
|
+
var cRange = cfun.getRange();
|
|
248
|
+
cfun.getTable(cRange[0], cRange[1], cWidth, tmpTable, 1);
|
|
249
|
+
|
|
250
|
+
if (iComps) {
|
|
251
|
+
for (var i = 0; i < cWidth * 3; i++) {
|
|
252
|
+
cTable[c * cWidth * 6 + i] = 255.0 * tmpTable[i];
|
|
253
|
+
cTable[c * cWidth * 6 + i + cWidth * 3] = 255.0 * tmpTable[i];
|
|
254
|
+
}
|
|
255
|
+
} else {
|
|
256
|
+
for (var _i = 0; _i < cWidth * 3; _i++) {
|
|
257
|
+
cTable[c * cWidth * 6 + _i] = 255.0 * tmpTable[_i];
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
model.colorTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
263
|
+
model.colorTexture.resetFormatAndType();
|
|
264
|
+
model.colorTexture.create2DFromRaw(cWidth, textureHeight, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
265
|
+
} else {
|
|
266
|
+
for (var _i2 = 0; _i2 < cWidth * 3; ++_i2) {
|
|
267
|
+
cTable[_i2] = 255.0 * _i2 / ((cWidth - 1) * 3);
|
|
268
|
+
cTable[_i2 + 1] = 255.0 * _i2 / ((cWidth - 1) * 3);
|
|
269
|
+
cTable[_i2 + 2] = 255.0 * _i2 / ((cWidth - 1) * 3);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
model.colorTextureString = cfunToString;
|
|
276
|
+
} // Build piecewise function buffer. This buffer is used either
|
|
277
|
+
// for component weighting or opacity, depending on whether we're
|
|
278
|
+
// rendering components independently or not.
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
var pwfunToString = computeFnToString(ppty, ppty.getPiecewiseFunction, numIComps);
|
|
282
|
+
|
|
283
|
+
if (model.pwfTextureString !== pwfunToString) {
|
|
284
|
+
var pwfWidth = 1024;
|
|
285
|
+
var pwfSize = pwfWidth * textureHeight;
|
|
286
|
+
var pwfTable = new Uint8Array(pwfSize);
|
|
287
|
+
var pwfun = ppty.getPiecewiseFunction(); // support case where pwfun is added/removed
|
|
288
|
+
|
|
289
|
+
model.pwfTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
290
|
+
model.pwfTexture.resetFormatAndType();
|
|
291
|
+
|
|
292
|
+
if (pwfun) {
|
|
293
|
+
var pwfFloatTable = new Float32Array(pwfSize);
|
|
294
|
+
|
|
295
|
+
var _tmpTable = new Float32Array(pwfWidth);
|
|
296
|
+
|
|
297
|
+
for (var _c = 0; _c < numIComps; ++_c) {
|
|
298
|
+
pwfun = ppty.getPiecewiseFunction(_c);
|
|
299
|
+
|
|
300
|
+
if (pwfun === null) {
|
|
301
|
+
// Piecewise constant max if no function supplied for this component
|
|
302
|
+
pwfFloatTable.fill(1.0);
|
|
303
|
+
} else {
|
|
304
|
+
var pwfRange = pwfun.getRange();
|
|
305
|
+
pwfun.getTable(pwfRange[0], pwfRange[1], pwfWidth, _tmpTable, 1); // adjust for sample distance etc
|
|
306
|
+
|
|
307
|
+
if (iComps) {
|
|
308
|
+
for (var _i3 = 0; _i3 < pwfWidth; _i3++) {
|
|
309
|
+
pwfFloatTable[_c * pwfWidth * 2 + _i3] = _tmpTable[_i3];
|
|
310
|
+
pwfFloatTable[_c * pwfWidth * 2 + _i3 + pwfWidth] = _tmpTable[_i3];
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
for (var _i4 = 0; _i4 < pwfWidth; _i4++) {
|
|
314
|
+
pwfFloatTable[_c * pwfWidth * 2 + _i4] = _tmpTable[_i4];
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
model.pwfTexture.create2DFromRaw(pwfWidth, textureHeight, 1, VtkDataTypes.FLOAT, pwfFloatTable);
|
|
321
|
+
} else {
|
|
322
|
+
// default is opaque
|
|
323
|
+
pwfTable.fill(255.0);
|
|
324
|
+
model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
model.pwfTextureString = pwfunToString;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
var vboString = "".concat(model.resliceGeom.getMTime(), "A").concat(model.renderable.getSlabThickness());
|
|
331
|
+
|
|
332
|
+
if (!model.tris.getCABO().getElementCount() || model.VBOBuildString !== vboString) {
|
|
333
|
+
var points = vtkDataArray.newInstance({
|
|
334
|
+
numberOfComponents: 3,
|
|
335
|
+
values: model.resliceGeom.getPoints().getData()
|
|
336
|
+
});
|
|
337
|
+
points.setName('points');
|
|
338
|
+
var cells = vtkDataArray.newInstance({
|
|
339
|
+
numberOfComponents: 1,
|
|
340
|
+
values: model.resliceGeom.getPolys().getData()
|
|
341
|
+
});
|
|
342
|
+
var options = {
|
|
343
|
+
points: points,
|
|
344
|
+
cellOffset: 0
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
if (model.renderable.getSlabThickness() > 0.0) {
|
|
348
|
+
var n = model.resliceGeom.getPointData().getNormals();
|
|
349
|
+
|
|
350
|
+
if (!n) {
|
|
351
|
+
vtkErrorMacro('Slab mode requested without normals');
|
|
352
|
+
} else {
|
|
353
|
+
options.normals = n;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
model.tris.getCABO().createVBO(cells, 'polys', Representation.SURFACE, options);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
model.VBOBuildString = vboString;
|
|
361
|
+
model.VBOBuildTime.modified();
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
publicAPI.updateShaders = function (cellBO, ren, actor) {
|
|
365
|
+
model.lastBoundBO = cellBO; // has something changed that would require us to recreate the shader?
|
|
366
|
+
|
|
367
|
+
if (publicAPI.getNeedToRebuildShaders(cellBO, ren, actor)) {
|
|
368
|
+
var shaders = {
|
|
369
|
+
Vertex: null,
|
|
370
|
+
Fragment: null,
|
|
371
|
+
Geometry: null
|
|
372
|
+
};
|
|
373
|
+
publicAPI.buildShaders(shaders, ren, actor); // compile and bind the program if needed
|
|
374
|
+
|
|
375
|
+
var newShader = model._openGLRenderWindow.getShaderCache().readyShaderProgramArray(shaders.Vertex, shaders.Fragment, shaders.Geometry); // if the shader changed reinitialize the VAO
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
if (newShader !== cellBO.getProgram()) {
|
|
379
|
+
cellBO.setProgram(newShader); // reset the VAO as the shader has changed
|
|
380
|
+
|
|
381
|
+
cellBO.getVAO().releaseGraphicsResources();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
cellBO.getShaderSourceTime().modified();
|
|
385
|
+
} else {
|
|
386
|
+
model._openGLRenderWindow.getShaderCache().readyShaderProgram(cellBO.getProgram());
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
cellBO.getVAO().bind();
|
|
390
|
+
publicAPI.setMapperShaderParameters(cellBO, ren, actor);
|
|
391
|
+
publicAPI.setCameraShaderParameters(cellBO, ren, actor);
|
|
392
|
+
publicAPI.setPropertyShaderParameters(cellBO, ren, actor);
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
publicAPI.setMapperShaderParameters = function (cellBO, ren, actor) {
|
|
396
|
+
var program = cellBO.getProgram();
|
|
397
|
+
|
|
398
|
+
if (cellBO.getCABO().getElementCount() && (model.VBOBuildTime.getMTime() > cellBO.getAttributeUpdateTime().getMTime() || cellBO.getShaderSourceTime().getMTime() > cellBO.getAttributeUpdateTime().getMTime())) {
|
|
399
|
+
// Set the 3D texture
|
|
400
|
+
if (program.isUniformUsed('texture1')) {
|
|
401
|
+
program.setUniformi('texture1', model.openGLTexture.getTextureUnit());
|
|
402
|
+
} // Set the plane vertex attributes
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
if (program.isAttributeUsed('vertexWC')) {
|
|
406
|
+
if (!cellBO.getVAO().addAttributeArray(program, cellBO.getCABO(), 'vertexWC', cellBO.getCABO().getVertexOffset(), cellBO.getCABO().getStride(), model.context.FLOAT, 3, model.context.FALSE)) {
|
|
407
|
+
vtkErrorMacro('Error setting vertexWC in shader VAO.');
|
|
408
|
+
}
|
|
409
|
+
} // If we are doing slab mode, we need normals
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
if (program.isAttributeUsed('normalWC')) {
|
|
413
|
+
if (!cellBO.getVAO().addAttributeArray(program, cellBO.getCABO(), 'normalWC', cellBO.getCABO().getNormalOffset(), cellBO.getCABO().getStride(), model.context.FLOAT, 3, model.context.FALSE)) {
|
|
414
|
+
vtkErrorMacro('Error setting normalWC in shader VAO.');
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (program.isUniformUsed('slabThickness')) {
|
|
419
|
+
program.setUniformf('slabThickness', model.renderable.getSlabThickness());
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (program.isUniformUsed('spacing')) {
|
|
423
|
+
program.setUniform3fv('spacing', model.currentInput.getSpacing());
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
if (program.isUniformUsed('slabType')) {
|
|
427
|
+
program.setUniformi('slabType', model.renderable.getSlabType());
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (program.isUniformUsed('slabType')) {
|
|
431
|
+
program.setUniformi('slabType', model.renderable.getSlabType());
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if (program.isUniformUsed('slabTrapezoid')) {
|
|
435
|
+
program.setUniformi('slabTrapezoid', model.renderable.getSlabTrapezoidIntegration());
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
var shiftScaleEnabled = cellBO.getCABO().getCoordShiftAndScaleEnabled();
|
|
439
|
+
var inverseShiftScaleMatrix = shiftScaleEnabled ? cellBO.getCABO().getInverseShiftAndScaleMatrix() : null; // Set the world->texture matrix
|
|
440
|
+
|
|
441
|
+
if (program.isUniformUsed('WCTCMatrix')) {
|
|
442
|
+
var image = model.currentInput;
|
|
443
|
+
mat4.identity(model.tmpMat4);
|
|
444
|
+
var bounds = image.getBounds();
|
|
445
|
+
var sc = [bounds[1] - bounds[0], bounds[3] - bounds[2], bounds[5] - bounds[4]];
|
|
446
|
+
var o = [bounds[0], bounds[2], bounds[4]];
|
|
447
|
+
var q = [0, 0, 0, 1];
|
|
448
|
+
mat4.fromRotationTranslationScale(model.tmpMat4, q, o, sc);
|
|
449
|
+
mat4.invert(model.tmpMat4, model.tmpMat4);
|
|
450
|
+
|
|
451
|
+
if (inverseShiftScaleMatrix) {
|
|
452
|
+
mat4.multiply(model.tmpMat4, model.tmpMat4, inverseShiftScaleMatrix);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
program.setUniformMatrix('WCTCMatrix', model.tmpMat4);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
cellBO.getAttributeUpdateTime().modified();
|
|
459
|
+
} // Depth request
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
if (model.haveSeenDepthRequest) {
|
|
463
|
+
cellBO.getProgram().setUniformi('depthRequest', model.renderDepth ? 1 : 0);
|
|
464
|
+
} // handle coincident
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
if (cellBO.getProgram().isUniformUsed('coffset')) {
|
|
468
|
+
var cp = publicAPI.getCoincidentParameters(ren, actor);
|
|
469
|
+
cellBO.getProgram().setUniformf('coffset', cp.offset); // cfactor isn't always used when coffset is.
|
|
470
|
+
|
|
471
|
+
if (cellBO.getProgram().isUniformUsed('cfactor')) {
|
|
472
|
+
cellBO.getProgram().setUniformf('cfactor', cp.factor);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
publicAPI.setCameraShaderParameters = function (cellBO, ren, actor) {
|
|
478
|
+
// [WMVP]C == {world, model, view, projection} coordinates
|
|
479
|
+
// e.g. WCPC == world to projection coordinate transformation
|
|
480
|
+
var keyMats = model._openGLCamera.getKeyMatrices(ren);
|
|
481
|
+
|
|
482
|
+
var actMats = model._openGLImageSlice.getKeyMatrices();
|
|
483
|
+
|
|
484
|
+
var shiftScaleEnabled = cellBO.getCABO().getCoordShiftAndScaleEnabled();
|
|
485
|
+
var inverseShiftScaleMatrix = shiftScaleEnabled ? cellBO.getCABO().getInverseShiftAndScaleMatrix() : null;
|
|
486
|
+
var program = cellBO.getProgram();
|
|
487
|
+
|
|
488
|
+
if (program.isUniformUsed('MCPCMatrix')) {
|
|
489
|
+
mat4.identity(model.tmpMat4);
|
|
490
|
+
program.setUniformMatrix('MCPCMatrix', safeMatrixMultiply([keyMats.wcpc, actMats.mcwc, inverseShiftScaleMatrix], mat4, model.tmpMat4));
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (program.isUniformUsed('MCVCMatrix')) {
|
|
494
|
+
mat4.identity(model.tmpMat4);
|
|
495
|
+
program.setUniformMatrix('MCVCMatrix', safeMatrixMultiply([keyMats.wcvc, actMats.mcwc, inverseShiftScaleMatrix], mat4, model.tmpMat4));
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
publicAPI.setPropertyShaderParameters = function (cellBO, ren, actor) {
|
|
500
|
+
var program = cellBO.getProgram();
|
|
501
|
+
var ppty = actor.getProperty();
|
|
502
|
+
var opacity = ppty.getOpacity();
|
|
503
|
+
program.setUniformf('opacity', opacity); // Component mix
|
|
504
|
+
// Independent components: Mixed according to component weights
|
|
505
|
+
// Dependent components: Mixed using the following logic:
|
|
506
|
+
// - 2 comps => LA
|
|
507
|
+
// - 3 comps => RGB + opacity from pwf
|
|
508
|
+
// - 4 comps => RGBA
|
|
509
|
+
|
|
510
|
+
var numComp = model.openGLTexture.getComponents();
|
|
511
|
+
var iComps = ppty.getIndependentComponents();
|
|
512
|
+
|
|
513
|
+
if (iComps) {
|
|
514
|
+
for (var i = 0; i < numComp; ++i) {
|
|
515
|
+
program.setUniformf("mix".concat(i), ppty.getComponentWeight(i));
|
|
516
|
+
}
|
|
517
|
+
} // Color opacity map
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
var volInfo = model.openGLTexture.getVolumeInfo(); // three levels of shift scale combined into one
|
|
521
|
+
// for performance in the fragment shader
|
|
522
|
+
|
|
523
|
+
for (var _i5 = 0; _i5 < numComp; _i5++) {
|
|
524
|
+
var cw = ppty.getColorWindow();
|
|
525
|
+
var cl = ppty.getColorLevel();
|
|
526
|
+
var target = iComps ? _i5 : 0;
|
|
527
|
+
var cfun = ppty.getRGBTransferFunction(target);
|
|
528
|
+
|
|
529
|
+
if (cfun && ppty.getUseLookupTableScalarRange()) {
|
|
530
|
+
var cRange = cfun.getRange();
|
|
531
|
+
cw = cRange[1] - cRange[0];
|
|
532
|
+
cl = 0.5 * (cRange[1] + cRange[0]);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
var scale = volInfo.scale[_i5] / cw;
|
|
536
|
+
var shift = (volInfo.offset[_i5] - cl) / cw + 0.5;
|
|
537
|
+
program.setUniformf("cshift".concat(_i5), shift);
|
|
538
|
+
program.setUniformf("cscale".concat(_i5), scale);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
var texColorUnit = model.colorTexture.getTextureUnit();
|
|
542
|
+
program.setUniformi('colorTexture1', texColorUnit); // pwf shift/scale
|
|
543
|
+
|
|
544
|
+
for (var _i6 = 0; _i6 < numComp; _i6++) {
|
|
545
|
+
var pwfScale = 1.0;
|
|
546
|
+
var pwfShift = 0.0;
|
|
547
|
+
|
|
548
|
+
var _target = iComps ? _i6 : 0;
|
|
549
|
+
|
|
550
|
+
var pwfun = ppty.getPiecewiseFunction(_target);
|
|
551
|
+
|
|
552
|
+
if (pwfun) {
|
|
553
|
+
var pwfRange = pwfun.getRange();
|
|
554
|
+
var length = pwfRange[1] - pwfRange[0];
|
|
555
|
+
var mid = 0.5 * (pwfRange[0] + pwfRange[1]);
|
|
556
|
+
pwfScale = volInfo.scale[_i6] / length;
|
|
557
|
+
pwfShift = (volInfo.offset[_i6] - mid) / length + 0.5;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
program.setUniformf("pwfshift".concat(_i6), pwfShift);
|
|
561
|
+
program.setUniformf("pwfscale".concat(_i6), pwfScale);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
var texOpacityUnit = model.pwfTexture.getTextureUnit();
|
|
565
|
+
program.setUniformi('pwfTexture1', texOpacityUnit); // Background color
|
|
566
|
+
|
|
567
|
+
program.setUniform4fv('backgroundColor', model.renderable.getBackgroundColor());
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
publicAPI.getNeedToRebuildShaders = function (cellBO, ren, actor) {
|
|
571
|
+
// has something changed that would require us to recreate the shader?
|
|
572
|
+
// candidates are
|
|
573
|
+
// property modified (representation interpolation and lighting)
|
|
574
|
+
// input modified
|
|
575
|
+
// light complexity changed
|
|
576
|
+
// render pass shader replacement changed
|
|
577
|
+
var tNumComp = model.openGLTexture.getComponents();
|
|
578
|
+
var iComp = actor.getProperty().getIndependentComponents();
|
|
579
|
+
var slabTh = model.renderable.getSlabThickness();
|
|
580
|
+
var slabType = model.renderable.getSlabType();
|
|
581
|
+
var slabTrap = model.renderable.getSlabTrapezoidIntegration(); // has the render pass shader replacement changed? Two options
|
|
582
|
+
|
|
583
|
+
var needRebuild = false;
|
|
584
|
+
|
|
585
|
+
if (!model.currentRenderPass && model.lastRenderPassShaderReplacement || model.currentRenderPass && model.currentRenderPass.getShaderReplacement() !== model.lastRenderPassShaderReplacement) {
|
|
586
|
+
needRebuild = true;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if (needRebuild || model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || cellBO.getProgram() === 0 || model.lastTextureComponents !== tNumComp || model.lastIndependentComponents !== iComp || model.lastSlabThickness !== slabTh || model.lastSlabType !== slabType || model.lastSlabTrapezoidIntegration !== slabTrap) {
|
|
590
|
+
model.lastHaveSeenDepthRequest = model.haveSeenDepthRequest;
|
|
591
|
+
model.lastTextureComponents = tNumComp;
|
|
592
|
+
model.lastIndependentComponents = iComp;
|
|
593
|
+
model.lastSlabThickness = slabTh;
|
|
594
|
+
model.lastSlabType = slabType;
|
|
595
|
+
model.lastSlabTrapezoidIntegration = slabTrap;
|
|
596
|
+
return true;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
return false;
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
publicAPI.getShaderTemplate = function (shaders, ren, actor) {
|
|
603
|
+
shaders.Vertex = vtkImageResliceMapperVS;
|
|
604
|
+
shaders.Fragment = vtkImageResliceMapperFS;
|
|
605
|
+
shaders.Geometry = '';
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
publicAPI.replaceShaderValues = function (shaders, ren, actor) {
|
|
609
|
+
publicAPI.replaceShaderTCoord(shaders, ren, actor);
|
|
610
|
+
publicAPI.replaceShaderPositionVC(shaders, ren, actor);
|
|
611
|
+
|
|
612
|
+
if (model.haveSeenDepthRequest) {
|
|
613
|
+
var FSSource = shaders.Fragment;
|
|
614
|
+
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Dec', 'uniform int depthRequest;').result;
|
|
615
|
+
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Impl', ['if (depthRequest == 1) {', 'float iz = floor(gl_FragCoord.z*65535.0 + 0.1);', 'float rf = floor(iz/256.0)/255.0;', 'float gf = mod(iz,256.0)/255.0;', 'gl_FragData[0] = vec4(rf, gf, 0.0, 1.0); }']).result;
|
|
616
|
+
shaders.Fragment = FSSource;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
publicAPI.replaceShaderCoincidentOffset(shaders, ren, actor);
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
publicAPI.replaceShaderTCoord = function (shaders, ren, actor) {
|
|
623
|
+
var VSSource = shaders.Vertex;
|
|
624
|
+
var GSSource = shaders.Geometry;
|
|
625
|
+
var FSSource = shaders.Fragment;
|
|
626
|
+
var tcoordVSDec = ['uniform mat4 WCTCMatrix;', 'out vec3 fragTexCoord;'];
|
|
627
|
+
var slabThickness = model.renderable.getSlabThickness();
|
|
628
|
+
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::TCoord::Dec', tcoordVSDec).result;
|
|
629
|
+
var tcoordVSImpl = ['fragTexCoord = (WCTCMatrix * vertexWC).xyz;'];
|
|
630
|
+
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::TCoord::Impl', tcoordVSImpl).result;
|
|
631
|
+
var tNumComp = model.openGLTexture.getComponents();
|
|
632
|
+
var iComps = actor.getProperty().getIndependentComponents();
|
|
633
|
+
var tcoordFSDec = ['in vec3 fragTexCoord;', 'uniform highp sampler3D texture1;', 'uniform mat4 WCTCMatrix;', // color shift and scale
|
|
634
|
+
'uniform float cshift0;', 'uniform float cscale0;', // pwf shift and scale
|
|
635
|
+
'uniform float pwfshift0;', 'uniform float pwfscale0;', // color and pwf textures
|
|
636
|
+
'uniform sampler2D colorTexture1;', 'uniform sampler2D pwfTexture1;', // opacity
|
|
637
|
+
'uniform float opacity;', // background color
|
|
638
|
+
'uniform vec4 backgroundColor;'];
|
|
639
|
+
|
|
640
|
+
if (iComps) {
|
|
641
|
+
for (var comp = 1; comp < tNumComp; comp++) {
|
|
642
|
+
tcoordFSDec = tcoordFSDec.concat([// color shift and scale
|
|
643
|
+
"uniform float cshift".concat(comp, ";"), "uniform float cscale".concat(comp, ";"), // weighting shift and scale
|
|
644
|
+
"uniform float pwfshift".concat(comp, ";"), "uniform float pwfscale".concat(comp, ";")]);
|
|
645
|
+
} // the heights defined below are the locations
|
|
646
|
+
// for the up to four components of the tfuns
|
|
647
|
+
// the tfuns have a height of 2XnumComps pixels so the
|
|
648
|
+
// values are computed to hit the middle of the two rows
|
|
649
|
+
// for that component
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
switch (tNumComp) {
|
|
653
|
+
case 1:
|
|
654
|
+
tcoordFSDec = tcoordFSDec.concat(['uniform float mix0;', '#define height0 0.5']);
|
|
655
|
+
break;
|
|
656
|
+
|
|
657
|
+
case 2:
|
|
658
|
+
tcoordFSDec = tcoordFSDec.concat(['uniform float mix0;', 'uniform float mix1;', '#define height0 0.25', '#define height1 0.75']);
|
|
659
|
+
break;
|
|
660
|
+
|
|
661
|
+
case 3:
|
|
662
|
+
tcoordFSDec = tcoordFSDec.concat(['uniform float mix0;', 'uniform float mix1;', 'uniform float mix2;', '#define height0 0.17', '#define height1 0.5', '#define height2 0.83']);
|
|
663
|
+
break;
|
|
664
|
+
|
|
665
|
+
case 4:
|
|
666
|
+
tcoordFSDec = tcoordFSDec.concat(['uniform float mix0;', 'uniform float mix1;', 'uniform float mix2;', 'uniform float mix3;', '#define height0 0.125', '#define height1 0.375', '#define height2 0.625', '#define height3 0.875']);
|
|
667
|
+
break;
|
|
668
|
+
|
|
669
|
+
default:
|
|
670
|
+
vtkErrorMacro('Unsupported number of independent coordinates.');
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
if (slabThickness > 0.0) {
|
|
675
|
+
tcoordFSDec = tcoordFSDec.concat(['uniform vec3 spacing;', 'uniform float slabThickness;', 'uniform int slabType;', 'uniform int slabTrapezoid;']);
|
|
676
|
+
tcoordFSDec = tcoordFSDec.concat(['vec4 compositeValue(vec4 currVal, vec4 valToComp, int trapezoid)', '{', ' vec4 retVal = vec4(1.0);', ' if (slabType == 0) // min', ' {', ' retVal = min(currVal, valToComp);', ' }', ' else if (slabType == 1) // max', ' {', ' retVal = max(currVal, valToComp);', ' }', ' else if (slabType == 3) // sum', ' {', ' retVal = currVal + (trapezoid > 0 ? 0.5 * valToComp : valToComp); ', ' }', ' else // mean', ' {', ' retVal = currVal + (trapezoid > 0 ? 0.5 * valToComp : valToComp); ', ' }', ' return retVal;', '}']);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Dec', tcoordFSDec).result;
|
|
680
|
+
var tcoordFSImpl = ['if (any(greaterThan(fragTexCoord, vec3(1.0))) || any(lessThan(fragTexCoord, vec3(0.0))))', '{', ' // set the background color and exit', ' gl_FragData[0] = backgroundColor;', ' return;', '}', 'vec4 tvalue = texture(texture1, fragTexCoord);'];
|
|
681
|
+
|
|
682
|
+
if (slabThickness > 0.0) {
|
|
683
|
+
tcoordFSImpl = tcoordFSImpl.concat(['// Get the first and last samples', 'int numSlices = 1;', 'vec3 normalxspacing = normalWCVSOutput * spacing * 0.5;', 'float distTraveled = length(normalxspacing);', 'int trapezoid = 0;', 'while (distTraveled < slabThickness * 0.5)', '{', ' distTraveled += length(normalxspacing);', ' float fnumSlices = float(numSlices);', ' if (distTraveled > slabThickness * 0.5)', ' {', ' // Before stepping outside the slab, sample at the boundaries', ' normalxspacing = normalWCVSOutput * slabThickness * 0.5 / fnumSlices;', ' trapezoid = slabTrapezoid;', ' }', ' vec3 fragTCoordNeg = (WCTCMatrix * vec4(vertexWCVSOutput.xyz - fnumSlices * normalxspacing, 1.0)).xyz;', ' if (!any(greaterThan(fragTCoordNeg, vec3(1.0))) && !any(lessThan(fragTCoordNeg, vec3(0.0))))', ' {', ' vec4 newVal = texture(texture1, fragTCoordNeg);', ' tvalue = compositeValue(tvalue, newVal, trapezoid);', ' numSlices += 1;', ' }', ' vec3 fragTCoordPos = (WCTCMatrix * vec4(vertexWCVSOutput.xyz + fnumSlices * normalxspacing, 1.0)).xyz;', ' if (!any(greaterThan(fragTCoordNeg, vec3(1.0))) && !any(lessThan(fragTCoordNeg, vec3(0.0))))', ' {', ' vec4 newVal = texture(texture1, fragTCoordPos);', ' tvalue = compositeValue(tvalue, newVal, trapezoid);', ' numSlices += 1;', ' }', '}', '// Finally, if slab type is *mean*, divide the sum by the numSlices', 'if (slabType == 2)', '{', ' tvalue = tvalue / float(numSlices);', '}']);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
if (iComps) {
|
|
687
|
+
var rgba = ['r', 'g', 'b', 'a'];
|
|
688
|
+
|
|
689
|
+
for (var _comp = 0; _comp < tNumComp; ++_comp) {
|
|
690
|
+
tcoordFSImpl = tcoordFSImpl.concat(["vec3 tcolor".concat(_comp, " = mix").concat(_comp, " * texture2D(colorTexture1, vec2(tvalue.").concat(rgba[_comp], " * cscale").concat(_comp, " + cshift").concat(_comp, ", height").concat(_comp, ")).rgb;"), "float compWeight".concat(_comp, " = mix").concat(_comp, " * texture2D(pwfTexture1, vec2(tvalue.").concat(rgba[_comp], " * pwfscale").concat(_comp, " + pwfshift").concat(_comp, ", height").concat(_comp, ")).r;")]);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
switch (tNumComp) {
|
|
694
|
+
case 1:
|
|
695
|
+
tcoordFSImpl = tcoordFSImpl.concat(['gl_FragData[0] = vec4(tcolor0.rgb, compWeight0 * opacity);']);
|
|
696
|
+
break;
|
|
697
|
+
|
|
698
|
+
case 2:
|
|
699
|
+
tcoordFSImpl = tcoordFSImpl.concat(['float weightSum = compWeight0 + compWeight1;', 'gl_FragData[0] = vec4(vec3((tcolor0.rgb * (compWeight0 / weightSum)) + (tcolor1.rgb * (compWeight1 / weightSum))), opacity);']);
|
|
700
|
+
break;
|
|
701
|
+
|
|
702
|
+
case 3:
|
|
703
|
+
tcoordFSImpl = tcoordFSImpl.concat(['float weightSum = compWeight0 + compWeight1 + compWeight2;', 'gl_FragData[0] = vec4(vec3((tcolor0.rgb * (compWeight0 / weightSum)) + (tcolor1.rgb * (compWeight1 / weightSum)) + (tcolor2.rgb * (compWeight2 / weightSum))), opacity);']);
|
|
704
|
+
break;
|
|
705
|
+
|
|
706
|
+
case 4:
|
|
707
|
+
tcoordFSImpl = tcoordFSImpl.concat(['float weightSum = compWeight0 + compWeight1 + compWeight2 + compWeight3;', 'gl_FragData[0] = vec4(vec3((tcolor0.rgb * (compWeight0 / weightSum)) + (tcolor1.rgb * (compWeight1 / weightSum)) + (tcolor2.rgb * (compWeight2 / weightSum)) + (tcolor3.rgb * (compWeight3 / weightSum))), opacity);']);
|
|
708
|
+
break;
|
|
709
|
+
|
|
710
|
+
default:
|
|
711
|
+
vtkErrorMacro('Unsupported number of independent coordinates.');
|
|
712
|
+
}
|
|
713
|
+
} else {
|
|
714
|
+
// dependent components
|
|
715
|
+
switch (tNumComp) {
|
|
716
|
+
case 1:
|
|
717
|
+
tcoordFSImpl = tcoordFSImpl.concat(['// Dependent components', 'float intensity = tvalue.r;', 'vec3 tcolor = texture2D(colorTexture1, vec2(intensity * cscale0 + cshift0, 0.5)).rgb;', 'float scalarOpacity = texture2D(pwfTexture1, vec2(intensity * pwfscale0 + pwfshift0, 0.5)).r;', 'gl_FragData[0] = vec4(tcolor, scalarOpacity * opacity);']);
|
|
718
|
+
break;
|
|
719
|
+
|
|
720
|
+
case 2:
|
|
721
|
+
tcoordFSImpl = tcoordFSImpl.concat(['float intensity = tvalue.r*cscale0 + cshift0;', 'gl_FragData[0] = vec4(texture2D(colorTexture1, vec2(intensity, 0.5)).rgb, pwfscale0*tvalue.g + pwfshift0);']);
|
|
722
|
+
break;
|
|
723
|
+
|
|
724
|
+
case 3:
|
|
725
|
+
tcoordFSImpl = tcoordFSImpl.concat(['vec4 tcolor = cscale0*tvalue + cshift0;', 'gl_FragData[0] = vec4(texture2D(colorTexture1, vec2(tcolor.r,0.5)).r,', ' texture2D(colorTexture1, vec2(tcolor.g,0.5)).r,', ' texture2D(colorTexture1, vec2(tcolor.b,0.5)).r, opacity);']);
|
|
726
|
+
break;
|
|
727
|
+
|
|
728
|
+
default:
|
|
729
|
+
tcoordFSImpl = tcoordFSImpl.concat(['vec4 tcolor = cscale0*tvalue + cshift0;', 'gl_FragData[0] = vec4(texture2D(colorTexture1, vec2(tcolor.r,0.5)).r,', ' texture2D(colorTexture1, vec2(tcolor.g,0.5)).r,', ' texture2D(colorTexture1, vec2(tcolor.b,0.5)).r, tcolor.a);']);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', tcoordFSImpl).result;
|
|
734
|
+
shaders.Vertex = VSSource;
|
|
735
|
+
shaders.Fragment = FSSource;
|
|
736
|
+
shaders.Geometry = GSSource;
|
|
737
|
+
};
|
|
738
|
+
|
|
739
|
+
publicAPI.replaceShaderPositionVC = function (shaders, ren, actor) {
|
|
740
|
+
var VSSource = shaders.Vertex;
|
|
741
|
+
var GSSource = shaders.Geometry;
|
|
742
|
+
var FSSource = shaders.Fragment;
|
|
743
|
+
var slabThickness = model.renderable.getSlabThickness();
|
|
744
|
+
var posVCVSDec = ['attribute vec4 vertexWC;']; // Add a unique hash to the shader to ensure that the shader program is unique to this mapper.
|
|
745
|
+
|
|
746
|
+
posVCVSDec = posVCVSDec.concat(["//".concat(publicAPI.getMTime()).concat(model.resliceGeomUpdateString)]);
|
|
747
|
+
|
|
748
|
+
if (slabThickness > 0.0) {
|
|
749
|
+
posVCVSDec = posVCVSDec.concat(['attribute vec3 normalWC;', 'varying vec3 normalWCVSOutput;', 'varying vec4 vertexWCVSOutput;']);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::PositionVC::Dec', posVCVSDec).result;
|
|
753
|
+
var posVCVSImpl = ['gl_Position = MCPCMatrix * vertexWC;'];
|
|
754
|
+
|
|
755
|
+
if (slabThickness > 0.0) {
|
|
756
|
+
posVCVSImpl = posVCVSImpl.concat(['normalWCVSOutput = normalWC;', 'vertexWCVSOutput = vertexWC;']);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::PositionVC::Impl', posVCVSImpl).result;
|
|
760
|
+
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::Camera::Dec', ['uniform mat4 MCPCMatrix;', 'uniform mat4 MCVCMatrix;']).result;
|
|
761
|
+
var posVCFSDec = [];
|
|
762
|
+
|
|
763
|
+
if (slabThickness > 0.0) {
|
|
764
|
+
posVCFSDec = posVCFSDec.concat(['varying vec3 normalWCVSOutput;', 'varying vec4 vertexWCVSOutput;']);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::PositionVC::Dec', posVCFSDec).result;
|
|
768
|
+
shaders.Vertex = VSSource;
|
|
769
|
+
shaders.Geometry = GSSource;
|
|
770
|
+
shaders.Fragment = FSSource;
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
function isVectorAxisAligned(n) {
|
|
774
|
+
vtkMath.normalize(n);
|
|
775
|
+
var tmpN = [0, 0, 0];
|
|
776
|
+
|
|
777
|
+
for (var i = 0; i < 3; ++i) {
|
|
778
|
+
vec3.zero(tmpN);
|
|
779
|
+
tmpN[i] = 1.0;
|
|
780
|
+
var dotP = vtkMath.dot(n, tmpN);
|
|
781
|
+
|
|
782
|
+
if (dotP < -0.999 || dotP > 0.999) {
|
|
783
|
+
return [true, i];
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
return [false, 2];
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
publicAPI.updateResliceGeometry = function () {
|
|
791
|
+
var resGeomString = '';
|
|
792
|
+
var image = model.currentInput;
|
|
793
|
+
var imageBounds = image === null || image === void 0 ? void 0 : image.getBounds(); // Orthogonal slicing by default
|
|
794
|
+
|
|
795
|
+
var orthoSlicing = true;
|
|
796
|
+
var orthoAxis = 2;
|
|
797
|
+
|
|
798
|
+
if (model.renderable.getSlicePolyData()) {
|
|
799
|
+
resGeomString = resGeomString.concat("PolyData".concat(model.renderable.getSlicePolyData().getMTime()));
|
|
800
|
+
} else if (model.renderable.getSlicePlane()) {
|
|
801
|
+
resGeomString = resGeomString.concat("Plane".concat(model.renderable.getSlicePlane().getMTime()));
|
|
802
|
+
|
|
803
|
+
if (image) {
|
|
804
|
+
resGeomString = resGeomString.concat("Image".concat(image.getMTime()));
|
|
805
|
+
} // Check to see if we can bypass oblique slicing related bounds computation
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
var _isVectorAxisAligned = isVectorAxisAligned(model.renderable.getSlicePlane().getNormal());
|
|
809
|
+
|
|
810
|
+
var _isVectorAxisAligned2 = _slicedToArray(_isVectorAxisAligned, 2);
|
|
811
|
+
|
|
812
|
+
orthoSlicing = _isVectorAxisAligned2[0];
|
|
813
|
+
orthoAxis = _isVectorAxisAligned2[1];
|
|
814
|
+
} else {
|
|
815
|
+
var _model$renderable$get;
|
|
816
|
+
|
|
817
|
+
// Create a default slice plane here
|
|
818
|
+
var plane = vtkPlane.newInstance();
|
|
819
|
+
plane.setNormal(0, 0, 1);
|
|
820
|
+
var bds = [0, 1, 0, 1, 0, 1];
|
|
821
|
+
|
|
822
|
+
if (image) {
|
|
823
|
+
bds = imageBounds;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
plane.setOrigin(bds[0], bds[2], 0.5 * (bds[5] + bds[4]));
|
|
827
|
+
model.renderable.setSlicePlane(plane);
|
|
828
|
+
resGeomString = resGeomString.concat("Plane".concat((_model$renderable$get = model.renderable.getSlicePlane()) === null || _model$renderable$get === void 0 ? void 0 : _model$renderable$get.getMTime()));
|
|
829
|
+
|
|
830
|
+
if (image) {
|
|
831
|
+
resGeomString = resGeomString.concat("Image".concat(image.getMTime()));
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
if (!model.resliceGeom || model.resliceGeomUpdateString !== resGeomString) {
|
|
836
|
+
if (model.renderable.getSlicePolyData()) {
|
|
837
|
+
model.resliceGeom = model.renderable.getSlicePolyData();
|
|
838
|
+
} else if (model.renderable.getSlicePlane()) {
|
|
839
|
+
var bounds = image ? imageBounds : [0, 1, 0, 1, 0, 1];
|
|
840
|
+
|
|
841
|
+
if (!orthoSlicing) {
|
|
842
|
+
var cube = vtkCubeSource.newInstance();
|
|
843
|
+
cube.setCenter(0.5 * (bounds[0] + bounds[1]), 0.5 * (bounds[2] + bounds[3]), 0.5 * (bounds[4] + bounds[5]));
|
|
844
|
+
cube.setXLength(bounds[1] - bounds[0]);
|
|
845
|
+
cube.setYLength(bounds[3] - bounds[2]);
|
|
846
|
+
cube.setZLength(bounds[5] - bounds[4]);
|
|
847
|
+
var cutter = vtkCutter.newInstance();
|
|
848
|
+
cutter.setInputConnection(cube.getOutputPort());
|
|
849
|
+
cutter.setCutFunction(model.renderable.getSlicePlane());
|
|
850
|
+
var pds = vtkClosedPolyLineToSurfaceFilter.newInstance();
|
|
851
|
+
pds.setInputConnection(cutter.getOutputPort());
|
|
852
|
+
pds.update();
|
|
853
|
+
model.resliceGeom = pds.getOutputData(); // The above method does not generate point normals
|
|
854
|
+
// Set it manually here.
|
|
855
|
+
|
|
856
|
+
var n = model.renderable.getSlicePlane().getNormal();
|
|
857
|
+
var npts = model.resliceGeom.getNumberOfPoints();
|
|
858
|
+
vtkMath.normalize(n);
|
|
859
|
+
var normalsData = new Float32Array(npts * 3);
|
|
860
|
+
|
|
861
|
+
for (var i = 0; i < npts; ++i) {
|
|
862
|
+
normalsData[3 * i] = n[0];
|
|
863
|
+
normalsData[3 * i + 1] = n[1];
|
|
864
|
+
normalsData[3 * i + 2] = n[2];
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
var normals = vtkDataArray.newInstance({
|
|
868
|
+
numberOfComponents: 3,
|
|
869
|
+
values: normalsData,
|
|
870
|
+
name: 'Normals'
|
|
871
|
+
});
|
|
872
|
+
model.resliceGeom.getPointData().setNormals(normals);
|
|
873
|
+
} else {
|
|
874
|
+
var ptsArray = new Float32Array(12);
|
|
875
|
+
var o = model.renderable.getSlicePlane().getOrigin();
|
|
876
|
+
var otherAxes = [(orthoAxis + 1) % 3, (orthoAxis + 2) % 3].sort();
|
|
877
|
+
var ptIdx = 0;
|
|
878
|
+
|
|
879
|
+
for (var _i7 = 0; _i7 < 2; ++_i7) {
|
|
880
|
+
for (var j = 0; j < 2; ++j) {
|
|
881
|
+
ptsArray[ptIdx + orthoAxis] = o[orthoAxis];
|
|
882
|
+
ptsArray[ptIdx + otherAxes[0]] = bounds[2 * otherAxes[0] + j];
|
|
883
|
+
ptsArray[ptIdx + otherAxes[1]] = bounds[2 * otherAxes[1] + _i7];
|
|
884
|
+
ptIdx += 3;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
var cellArray = new Uint16Array(8);
|
|
889
|
+
cellArray[0] = 3;
|
|
890
|
+
cellArray[1] = 0;
|
|
891
|
+
cellArray[2] = 1;
|
|
892
|
+
cellArray[3] = 3;
|
|
893
|
+
cellArray[4] = 3;
|
|
894
|
+
cellArray[5] = 0;
|
|
895
|
+
cellArray[6] = 3;
|
|
896
|
+
cellArray[7] = 2;
|
|
897
|
+
|
|
898
|
+
var _n = model.renderable.getSlicePlane().getNormal();
|
|
899
|
+
|
|
900
|
+
vtkMath.normalize(_n);
|
|
901
|
+
|
|
902
|
+
var _normalsData = new Float32Array(12);
|
|
903
|
+
|
|
904
|
+
for (var _i8 = 0; _i8 < 4; ++_i8) {
|
|
905
|
+
_normalsData[3 * _i8] = _n[0];
|
|
906
|
+
_normalsData[3 * _i8 + 1] = _n[1];
|
|
907
|
+
_normalsData[3 * _i8 + 2] = _n[2];
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
if (!model.resliceGeom) {
|
|
911
|
+
model.resliceGeom = vtkPolyData.newInstance();
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
model.resliceGeom.getPoints().setData(ptsArray, 3);
|
|
915
|
+
model.resliceGeom.getPolys().setData(cellArray, 1);
|
|
916
|
+
|
|
917
|
+
var _normals = vtkDataArray.newInstance({
|
|
918
|
+
numberOfComponents: 3,
|
|
919
|
+
values: _normalsData,
|
|
920
|
+
name: 'Normals'
|
|
921
|
+
});
|
|
922
|
+
|
|
923
|
+
model.resliceGeom.getPointData().setNormals(_normals);
|
|
924
|
+
model.resliceGeom.modified();
|
|
925
|
+
}
|
|
926
|
+
} else {
|
|
927
|
+
vtkErrorMacro('Something went wrong.', 'A default slice plane should have been created in the beginning of', 'updateResliceGeometry.');
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
model.resliceGeomUpdateString = resGeomString;
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
|
|
934
|
+
publicAPI.setOpenGLTexture = function (oglTex) {
|
|
935
|
+
if (oglTex) {
|
|
936
|
+
model.openGLTexture = oglTex;
|
|
937
|
+
model._externalOpenGLTexture = true;
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
} // ----------------------------------------------------------------------------
|
|
941
|
+
// Object factory
|
|
942
|
+
// ----------------------------------------------------------------------------
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
var DEFAULT_VALUES = {
|
|
946
|
+
VBOBuildTime: {},
|
|
947
|
+
VBOBuildString: null,
|
|
948
|
+
haveSeenDepthRequest: false,
|
|
949
|
+
lastHaveSeenDepthRequest: false,
|
|
950
|
+
lastIndependentComponents: false,
|
|
951
|
+
lastTextureComponents: 0,
|
|
952
|
+
lastSlabThickness: 0,
|
|
953
|
+
lastSlabTrapezoidIntegration: 0,
|
|
954
|
+
lastSlabType: -1,
|
|
955
|
+
openGLTexture: null,
|
|
956
|
+
openGLTextureString: null,
|
|
957
|
+
colorTextureString: null,
|
|
958
|
+
pwfTextureString: null,
|
|
959
|
+
resliceGeom: null,
|
|
960
|
+
resliceGeomUpdateString: null,
|
|
961
|
+
tris: null,
|
|
962
|
+
colorTexture: null,
|
|
963
|
+
pwfTexture: null,
|
|
964
|
+
_externalOpenGLTexture: false
|
|
965
|
+
}; // ----------------------------------------------------------------------------
|
|
966
|
+
|
|
967
|
+
function extend(publicAPI, model) {
|
|
968
|
+
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
969
|
+
Object.assign(model, DEFAULT_VALUES, initialValues); // Inheritance
|
|
970
|
+
|
|
971
|
+
vtkViewNode.extend(publicAPI, model, initialValues);
|
|
972
|
+
vtkReplacementShaderMapper.implementReplaceShaderCoincidentOffset(publicAPI, model, initialValues);
|
|
973
|
+
vtkReplacementShaderMapper.implementBuildShadersWithReplacements(publicAPI, model, initialValues);
|
|
974
|
+
model.tris = vtkHelper.newInstance();
|
|
975
|
+
model.openGLTexture = vtkOpenGLTexture.newInstance();
|
|
976
|
+
model.colorTexture = vtkOpenGLTexture.newInstance();
|
|
977
|
+
model.pwfTexture = vtkOpenGLTexture.newInstance();
|
|
978
|
+
model.VBOBuildTime = {};
|
|
979
|
+
obj(model.VBOBuildTime); // model.modelToView = mat4.identity(new Float64Array(16));
|
|
980
|
+
|
|
981
|
+
model.tmpMat4 = mat4.identity(new Float64Array(16));
|
|
982
|
+
get(publicAPI, model, ['openGLTexture']); // Object methods
|
|
983
|
+
|
|
984
|
+
vtkOpenGLImageResliceMapper(publicAPI, model);
|
|
985
|
+
} // ----------------------------------------------------------------------------
|
|
986
|
+
|
|
987
|
+
var newInstance = newInstance$1(extend, 'vtkOpenGLImageResliceMapper'); // ----------------------------------------------------------------------------
|
|
988
|
+
|
|
989
|
+
var vtkImageResliceMapper = {
|
|
990
|
+
newInstance: newInstance,
|
|
991
|
+
extend: extend
|
|
992
|
+
}; // Register ourself to OpenGL backend if imported
|
|
993
|
+
|
|
994
|
+
registerOverride('vtkImageResliceMapper', newInstance);
|
|
995
|
+
|
|
996
|
+
export { vtkImageResliceMapper as default, extend, newInstance };
|