@kitware/vtk.js 22.5.1 → 22.5.5
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/Common/Core/DataArray.d.ts +32 -21
- package/Common/Core/DataArray.js +51 -17
- package/Rendering/Core/ScalarBarActor.js +3 -28
- package/Rendering/Core/Texture.js +44 -4
- package/Rendering/Misc/SynchronizableRenderWindow.d.ts +2 -2
- package/Rendering/OpenGL/HardwareSelector.js +2 -2
- package/Rendering/OpenGL/Texture.js +38 -11
- package/Rendering/OpenGL.js +1 -0
- package/Rendering/WebGPU/BufferManager/Constants.js +2 -1
- package/Rendering/WebGPU/BufferManager.js +24 -69
- package/Rendering/WebGPU/Device.js +73 -1
- package/Rendering/WebGPU/ImageMapper.js +1 -1
- package/Rendering/WebGPU/PolyDataMapper.js +35 -28
- package/Rendering/WebGPU/RenderEncoder.js +1 -1
- package/Rendering/WebGPU/SphereMapper.js +6 -6
- package/Rendering/WebGPU/StickMapper.js +8 -8
- package/Rendering/WebGPU/Texture.js +23 -2
- package/Rendering/WebGPU/TextureManager.js +46 -48
- package/Rendering/WebGPU/VolumePass.js +6 -7
- package/Rendering/WebGPU/VolumePassFSQ.js +1 -1
- package/Rendering/WebGPU.js +16 -0
- package/package.json +1 -1
|
@@ -31,21 +31,21 @@ export interface vtkDataArray extends vtkObject {
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Get the component for a given tupleIdx.
|
|
34
|
-
* @param {Number} tupleIdx
|
|
34
|
+
* @param {Number} tupleIdx
|
|
35
35
|
* @param {Number} [componentIndex] (default: 0)
|
|
36
36
|
*/
|
|
37
37
|
getComponent(tupleIdx: number, componentIndex?: number): number;
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* Set the component value for a given tupleIdx and componentIndex.
|
|
41
|
-
* @param {Number} tupleIdx
|
|
42
|
-
* @param {Number} componentIndex
|
|
43
|
-
* @param {Number} value
|
|
41
|
+
* @param {Number} tupleIdx
|
|
42
|
+
* @param {Number} componentIndex
|
|
43
|
+
* @param {Number} value
|
|
44
44
|
*/
|
|
45
45
|
setComponent(tupleIdx: number, componentIndex: number, value: number): void;
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
48
|
+
*
|
|
49
49
|
*/
|
|
50
50
|
getData(): TypedArray;
|
|
51
51
|
|
|
@@ -57,22 +57,22 @@ export interface vtkDataArray extends vtkObject {
|
|
|
57
57
|
getRange(componentIndex?: number): vtkRange;
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
|
-
*
|
|
61
|
-
* @param {vtkRange} rangeValue
|
|
62
|
-
* @param {Number} componentIndex
|
|
60
|
+
*
|
|
61
|
+
* @param {vtkRange} rangeValue
|
|
62
|
+
* @param {Number} componentIndex
|
|
63
63
|
*/
|
|
64
64
|
setRange(rangeValue: vtkRange, componentIndex: number): [number, number];
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
|
-
*
|
|
68
|
-
* @param {Number} idx
|
|
69
|
-
* @param {Number[]} tuple
|
|
67
|
+
*
|
|
68
|
+
* @param {Number} idx
|
|
69
|
+
* @param {Number[]} tuple
|
|
70
70
|
*/
|
|
71
71
|
setTuple(idx: number, tuple: number[]): void;
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
74
|
*
|
|
75
|
-
* @param {Number} idx
|
|
75
|
+
* @param {Number} idx
|
|
76
76
|
* @param {Number[]} [tupleToFill] (default [])
|
|
77
77
|
*/
|
|
78
78
|
getTuple(idx: number, tupleToFill?: number[]): number[];
|
|
@@ -99,42 +99,42 @@ export interface vtkDataArray extends vtkObject {
|
|
|
99
99
|
getNumberOfTuples(): number;
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
|
-
*
|
|
102
|
+
*
|
|
103
103
|
*/
|
|
104
104
|
getDataType(): string;
|
|
105
105
|
|
|
106
106
|
/**
|
|
107
|
-
*
|
|
107
|
+
*
|
|
108
108
|
*/
|
|
109
109
|
newClone(): vtkDataArray;
|
|
110
110
|
|
|
111
111
|
/**
|
|
112
|
-
*
|
|
112
|
+
*
|
|
113
113
|
*/
|
|
114
114
|
getName(): string;
|
|
115
115
|
|
|
116
116
|
/**
|
|
117
|
-
*
|
|
118
|
-
* @param {TypedArray} typedArray
|
|
119
|
-
* @param {Number} [numberOfComponents]
|
|
117
|
+
*
|
|
118
|
+
* @param {TypedArray} typedArray
|
|
119
|
+
* @param {Number} [numberOfComponents]
|
|
120
120
|
*/
|
|
121
121
|
setData(typedArray: TypedArray, numberOfComponents?: number): void;
|
|
122
122
|
|
|
123
123
|
/**
|
|
124
|
-
*
|
|
124
|
+
*
|
|
125
125
|
*/
|
|
126
126
|
getState(): object;
|
|
127
127
|
|
|
128
128
|
// --- via macro --
|
|
129
129
|
|
|
130
130
|
/**
|
|
131
|
-
*
|
|
131
|
+
*
|
|
132
132
|
*/
|
|
133
133
|
setName(name: string): boolean;
|
|
134
134
|
|
|
135
135
|
/**
|
|
136
136
|
* Set the dimension (n) of the components.
|
|
137
|
-
* @param {Number} numberOfComponents
|
|
137
|
+
* @param {Number} numberOfComponents
|
|
138
138
|
*/
|
|
139
139
|
setNumberOfComponents(numberOfComponents: number): boolean;
|
|
140
140
|
}
|
|
@@ -160,6 +160,16 @@ export interface vtkDataArray extends vtkObject {
|
|
|
160
160
|
export function computeRange(values: number[], component?: number, numberOfComponents?: number): vtkRange;
|
|
161
161
|
|
|
162
162
|
/**
|
|
163
|
+
* Compute range of a given array, it only supports 1D arrays.
|
|
164
|
+
*
|
|
165
|
+
* @param {Number[]} values Array to go through to extract the range from
|
|
166
|
+
* @param {Number} offset offset index to select the desired component in the tuple
|
|
167
|
+
* @param {Number} numberOfComponents size of tuple in a multi-channel array
|
|
168
|
+
*/
|
|
169
|
+
export function fastComputeRange(values: number[], offset: number, numberOfComponents: number): vtkRange;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @deprecated please use `fastComputeRange` instead
|
|
163
173
|
* Create helper object that can be used to gather min, max, count, sum of
|
|
164
174
|
* a set of values.
|
|
165
175
|
*/
|
|
@@ -242,6 +252,7 @@ export declare const vtkDataArray: {
|
|
|
242
252
|
// static
|
|
243
253
|
computeRange: typeof computeRange,
|
|
244
254
|
createRangeHelper: typeof createRangeHelper,
|
|
255
|
+
fastComputeRange: typeof fastComputeRange,
|
|
245
256
|
getDataType: typeof getDataType,
|
|
246
257
|
getMaxNorm: typeof getMaxNorm,
|
|
247
258
|
// constants
|
package/Common/Core/DataArray.js
CHANGED
|
@@ -10,6 +10,45 @@ var DefaultDataType = Constants.DefaultDataType;
|
|
|
10
10
|
var TUPLE_HOLDER = []; // ----------------------------------------------------------------------------
|
|
11
11
|
// Global methods
|
|
12
12
|
// ----------------------------------------------------------------------------
|
|
13
|
+
// Original source from https://www.npmjs.com/package/compute-range
|
|
14
|
+
// Modified to accept type arrays
|
|
15
|
+
|
|
16
|
+
function fastComputeRange(arr, offset, numberOfComponents) {
|
|
17
|
+
var len = arr.length;
|
|
18
|
+
var min;
|
|
19
|
+
var max;
|
|
20
|
+
var x;
|
|
21
|
+
var i;
|
|
22
|
+
|
|
23
|
+
if (len === 0) {
|
|
24
|
+
return {
|
|
25
|
+
min: Number.MAX_VALUE,
|
|
26
|
+
max: -Number.MAX_VALUE
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
min = arr[offset];
|
|
31
|
+
max = min;
|
|
32
|
+
|
|
33
|
+
for (i = offset; i < len; i += numberOfComponents) {
|
|
34
|
+
x = arr[i];
|
|
35
|
+
|
|
36
|
+
if (x < min) {
|
|
37
|
+
min = x;
|
|
38
|
+
} else if (x > max) {
|
|
39
|
+
max = x;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
min: min,
|
|
45
|
+
max: max
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* @deprecated please use fastComputeRange instead
|
|
50
|
+
*/
|
|
51
|
+
|
|
13
52
|
|
|
14
53
|
function createRangeHelper() {
|
|
15
54
|
var min = Number.MAX_VALUE;
|
|
@@ -50,33 +89,27 @@ function createRangeHelper() {
|
|
|
50
89
|
function computeRange(values) {
|
|
51
90
|
var component = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
52
91
|
var numberOfComponents = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
|
|
53
|
-
var helper = createRangeHelper();
|
|
54
|
-
var size = values.length;
|
|
55
|
-
var value = 0;
|
|
56
92
|
|
|
57
93
|
if (component < 0 && numberOfComponents > 1) {
|
|
58
94
|
// Compute magnitude
|
|
59
|
-
|
|
60
|
-
|
|
95
|
+
var size = values.length;
|
|
96
|
+
var numberOfValues = size / numberOfComponents;
|
|
97
|
+
var data = new Float64Array(numberOfValues);
|
|
61
98
|
|
|
62
|
-
|
|
63
|
-
|
|
99
|
+
for (var i = 0, j = 0; i < numberOfValues; ++i) {
|
|
100
|
+
var _i;
|
|
101
|
+
|
|
102
|
+
for (var nextJ = j + numberOfComponents; j < nextJ; ++j) {
|
|
103
|
+
data[i] += values[j] * values[j];
|
|
64
104
|
}
|
|
65
105
|
|
|
66
|
-
|
|
67
|
-
helper.add(value);
|
|
106
|
+
_i = i, data[_i] = Math.pow(data[_i], 0.5);
|
|
68
107
|
}
|
|
69
108
|
|
|
70
|
-
return
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
var offset = component < 0 ? 0 : component;
|
|
74
|
-
|
|
75
|
-
for (var _i = offset; _i < size; _i += numberOfComponents) {
|
|
76
|
-
helper.add(values[_i]);
|
|
109
|
+
return fastComputeRange(data, 0, 1);
|
|
77
110
|
}
|
|
78
111
|
|
|
79
|
-
return
|
|
112
|
+
return fastComputeRange(values, component < 0 ? 0 : component, numberOfComponents);
|
|
80
113
|
}
|
|
81
114
|
|
|
82
115
|
function ensureRangeSize(rangeArray) {
|
|
@@ -116,6 +149,7 @@ function getMaxNorm(normArray) {
|
|
|
116
149
|
var STATIC = {
|
|
117
150
|
computeRange: computeRange,
|
|
118
151
|
createRangeHelper: createRangeHelper,
|
|
152
|
+
fastComputeRange: fastComputeRange,
|
|
119
153
|
getDataType: getDataType,
|
|
120
154
|
getMaxNorm: getMaxNorm
|
|
121
155
|
}; // ----------------------------------------------------------------------------
|
|
@@ -221,22 +221,6 @@ function vtkScalarBarActorHelper(publicAPI, model) {
|
|
|
221
221
|
model.lastRedrawTime.modified();
|
|
222
222
|
model.forceViewUpdate = false;
|
|
223
223
|
}
|
|
224
|
-
}; // The text atlas is an image and as loading images is async we call this when
|
|
225
|
-
// the promise resolves. The old texture is used until then
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
publicAPI.completedImage = function (doUpdate) {
|
|
229
|
-
if (model.nextImage && model.nextImage.complete) {
|
|
230
|
-
model.tmTexture.setImage(model.nextImage);
|
|
231
|
-
model.nextImage = null;
|
|
232
|
-
model._tmAtlas = model._nextAtlas;
|
|
233
|
-
model._nextAtlas = null;
|
|
234
|
-
|
|
235
|
-
if (doUpdate) {
|
|
236
|
-
model.forceViewUpdate = true;
|
|
237
|
-
model.renderWindow.render();
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
224
|
}; // create the texture map atlas that contains the rendering of
|
|
241
225
|
// all the text strings. Only needs to be called when the text strings
|
|
242
226
|
// have changed (labels and ticks)
|
|
@@ -317,19 +301,10 @@ function vtkScalarBarActorHelper(publicAPI, model) {
|
|
|
317
301
|
applyTextStyle(model.tmContext, value.textStyle);
|
|
318
302
|
model.tmContext.fillText(key, 1, value.startingHeight + value.height - 1);
|
|
319
303
|
});
|
|
320
|
-
|
|
321
|
-
image.src = model.tmCanvas.toDataURL('image/png');
|
|
322
|
-
model.nextImage = image;
|
|
323
|
-
model._nextAtlas = newTmAtlas;
|
|
324
|
-
|
|
325
|
-
if (image.complete) {
|
|
326
|
-
publicAPI.completedImage(false);
|
|
327
|
-
} else {
|
|
328
|
-
image.addEventListener('load', function () {
|
|
329
|
-
publicAPI.completedImage(true);
|
|
330
|
-
});
|
|
331
|
-
}
|
|
304
|
+
model.tmTexture.setCanvas(model.tmCanvas); // mark as modified since the canvas typically doesn't change
|
|
332
305
|
|
|
306
|
+
model.tmTexture.modified();
|
|
307
|
+
model._tmAtlas = newTmAtlas;
|
|
333
308
|
return results;
|
|
334
309
|
};
|
|
335
310
|
|
|
@@ -13,14 +13,52 @@ function vtkTexture(publicAPI, model) {
|
|
|
13
13
|
publicAPI.modified();
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
+
publicAPI.setJsImageData = function (imageData) {
|
|
17
|
+
if (model.jsImageData === imageData) {
|
|
18
|
+
return;
|
|
19
|
+
} // clear other entries
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
if (imageData !== null) {
|
|
23
|
+
publicAPI.setInputData(null);
|
|
24
|
+
publicAPI.setInputConnection(null);
|
|
25
|
+
model.image = null;
|
|
26
|
+
model.canvas = null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
model.jsImageData = imageData;
|
|
30
|
+
model.imageLoaded = true;
|
|
31
|
+
publicAPI.modified();
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
publicAPI.setCanvas = function (canvas) {
|
|
35
|
+
if (model.canvas === canvas) {
|
|
36
|
+
return;
|
|
37
|
+
} // clear other entries
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
if (canvas !== null) {
|
|
41
|
+
publicAPI.setInputData(null);
|
|
42
|
+
publicAPI.setInputConnection(null);
|
|
43
|
+
model.image = null;
|
|
44
|
+
model.jsImageData = null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
model.canvas = canvas;
|
|
48
|
+
publicAPI.modified();
|
|
49
|
+
};
|
|
50
|
+
|
|
16
51
|
publicAPI.setImage = function (image) {
|
|
17
52
|
if (model.image === image) {
|
|
18
53
|
return;
|
|
19
|
-
}
|
|
54
|
+
} // clear other entries
|
|
55
|
+
|
|
20
56
|
|
|
21
57
|
if (image !== null) {
|
|
22
58
|
publicAPI.setInputData(null);
|
|
23
59
|
publicAPI.setInputConnection(null);
|
|
60
|
+
model.canvas = null;
|
|
61
|
+
model.jsImageData = null;
|
|
24
62
|
}
|
|
25
63
|
|
|
26
64
|
model.image = image;
|
|
@@ -44,7 +82,9 @@ var DEFAULT_VALUES = {
|
|
|
44
82
|
interpolate: false,
|
|
45
83
|
edgeClamp: false,
|
|
46
84
|
image: null,
|
|
47
|
-
|
|
85
|
+
canvas: null,
|
|
86
|
+
imageLoaded: false,
|
|
87
|
+
jsImageData: null
|
|
48
88
|
}; // ----------------------------------------------------------------------------
|
|
49
89
|
|
|
50
90
|
function extend(publicAPI, model) {
|
|
@@ -53,8 +93,8 @@ function extend(publicAPI, model) {
|
|
|
53
93
|
|
|
54
94
|
macro.obj(publicAPI, model);
|
|
55
95
|
macro.algo(publicAPI, model, 6, 0);
|
|
56
|
-
macro.get(publicAPI, model, ['imageLoaded']);
|
|
57
|
-
macro.setGet(publicAPI, model, ['repeat', 'edgeClamp', 'interpolate'
|
|
96
|
+
macro.get(publicAPI, model, ['canvas', 'image', 'jsImageData', 'imageLoaded']);
|
|
97
|
+
macro.setGet(publicAPI, model, ['repeat', 'edgeClamp', 'interpolate']);
|
|
58
98
|
vtkTexture(publicAPI, model);
|
|
59
99
|
} // ----------------------------------------------------------------------------
|
|
60
100
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import vtkRenderWindow, { IRenderWindowInitialValues } from '@kitware/vtk.js/Rendering/Core/RenderWindow';
|
|
2
2
|
|
|
3
3
|
// Keeps state for client / server scene synchronization.
|
|
4
4
|
export interface SynchContext {
|
|
@@ -33,7 +33,7 @@ export interface IInitialValues extends IRenderWindowInitialValues {
|
|
|
33
33
|
|
|
34
34
|
// Server-side view state.
|
|
35
35
|
export interface ViewState {
|
|
36
|
-
id:
|
|
36
|
+
id: string;
|
|
37
37
|
// vtk object type.
|
|
38
38
|
type: string;
|
|
39
39
|
// vtk object mtime.
|
|
@@ -57,7 +57,7 @@ function getPixelInformationWithData(buffdata, inDisplayPosition, maxDistance, o
|
|
|
57
57
|
var displayPosition = [inDisplayPosition[0] - buffdata.area[0], inDisplayPosition[1] - buffdata.area[1]];
|
|
58
58
|
var actorid = convert(displayPosition[0], displayPosition[1], buffdata.pixBuffer[PassTypes.ACTOR_PASS], buffdata.area);
|
|
59
59
|
|
|
60
|
-
if (actorid <= 0) {
|
|
60
|
+
if (actorid <= 0 || actorid - idOffset >= buffdata.props.length) {
|
|
61
61
|
// the pixel did not hit any actor.
|
|
62
62
|
return null;
|
|
63
63
|
}
|
|
@@ -520,7 +520,7 @@ function vtkOpenGLHardwareSelector(publicAPI, model) {
|
|
|
520
520
|
var displayPosition = [inDisplayPosition[0] - model.area[0], inDisplayPosition[1] - model.area[1]];
|
|
521
521
|
var actorid = convert(displayPosition[0], displayPosition[1], model.pixBuffer[PassTypes.ACTOR_PASS], model.area);
|
|
522
522
|
|
|
523
|
-
if (actorid <= 0) {
|
|
523
|
+
if (actorid <= 0 || actorid - idOffset >= model.props.length) {
|
|
524
524
|
// the pixel did not hit any actor.
|
|
525
525
|
return null;
|
|
526
526
|
}
|
|
@@ -78,7 +78,36 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
78
78
|
publicAPI.sendParameters();
|
|
79
79
|
model.textureBuildTime.modified();
|
|
80
80
|
}
|
|
81
|
-
} // if we have
|
|
81
|
+
} // if we have a canvas
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if (model.renderable.getCanvas() !== null) {
|
|
85
|
+
if (model.renderable.getInterpolate()) {
|
|
86
|
+
model.generateMipmap = true;
|
|
87
|
+
publicAPI.setMinificationFilter(Filter.LINEAR_MIPMAP_LINEAR);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
var canvas = model.renderable.getCanvas();
|
|
91
|
+
publicAPI.create2DFromRaw(canvas.width, canvas.height, 4, VtkDataTypes.UNSIGNED_CHAR, canvas, true);
|
|
92
|
+
publicAPI.activate();
|
|
93
|
+
publicAPI.sendParameters();
|
|
94
|
+
model.textureBuildTime.modified();
|
|
95
|
+
} // if we have jsImageData
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if (model.renderable.getJsImageData() !== null) {
|
|
99
|
+
var jsid = model.renderable.getJsImageData();
|
|
100
|
+
|
|
101
|
+
if (model.renderable.getInterpolate()) {
|
|
102
|
+
model.generateMipmap = true;
|
|
103
|
+
publicAPI.setMinificationFilter(Filter.LINEAR_MIPMAP_LINEAR);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
publicAPI.create2DFromRaw(jsid.width, jsid.height, 4, VtkDataTypes.UNSIGNED_CHAR, jsid.data, true);
|
|
107
|
+
publicAPI.activate();
|
|
108
|
+
publicAPI.sendParameters();
|
|
109
|
+
model.textureBuildTime.modified();
|
|
110
|
+
} // if we have InputData
|
|
82
111
|
|
|
83
112
|
|
|
84
113
|
var input = model.renderable.getInputData(0);
|
|
@@ -678,6 +707,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
678
707
|
|
|
679
708
|
|
|
680
709
|
publicAPI.create2DFromRaw = function (width, height, numComps, dataType, data) {
|
|
710
|
+
var flip = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
|
|
681
711
|
// Now determine the texture parameters using the arguments.
|
|
682
712
|
publicAPI.getOpenGLDataType(dataType);
|
|
683
713
|
publicAPI.getInternalFormat(dataType, numComps);
|
|
@@ -701,13 +731,18 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
701
731
|
var dataArray = [data];
|
|
702
732
|
var pixData = updateArrayDataType(dataType, dataArray);
|
|
703
733
|
var scaledData = scaleTextureToHighestPowerOfTwo(pixData); // Source texture data from the PBO.
|
|
704
|
-
// model.context.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
|
705
734
|
|
|
735
|
+
model.context.pixelStorei(model.context.UNPACK_FLIP_Y_WEBGL, flip);
|
|
706
736
|
model.context.pixelStorei(model.context.UNPACK_ALIGNMENT, 1);
|
|
707
737
|
model.context.texImage2D(model.target, 0, model.internalFormat, model.width, model.height, 0, model.format, model.openGLDataType, scaledData[0]);
|
|
708
738
|
|
|
709
739
|
if (model.generateMipmap) {
|
|
710
740
|
model.context.generateMipmap(model.target);
|
|
741
|
+
} // always reset the flip
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
if (flip) {
|
|
745
|
+
model.context.pixelStorei(model.context.UNPACK_FLIP_Y_WEBGL, false);
|
|
711
746
|
}
|
|
712
747
|
|
|
713
748
|
publicAPI.deactivate();
|
|
@@ -867,15 +902,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
867
902
|
var ctx = canvas.getContext('2d');
|
|
868
903
|
ctx.translate(0, canvas.height);
|
|
869
904
|
ctx.scale(1, -1);
|
|
870
|
-
ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
|
|
871
|
-
// canvases from working properly with webGL textures. By getting any
|
|
872
|
-
// image data from the canvas, this works around the bug. See
|
|
873
|
-
// https://bugs.chromium.org/p/chromium/issues/detail?id=896307
|
|
874
|
-
|
|
875
|
-
if (navigator.userAgent.indexOf('Chrome/69') >= 0) {
|
|
876
|
-
ctx.getImageData(0, 0, 1, 1);
|
|
877
|
-
}
|
|
878
|
-
|
|
905
|
+
ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
|
|
879
906
|
var safeImage = canvas;
|
|
880
907
|
model.context.texImage2D(model.target, 0, model.internalFormat, model.format, model.openGLDataType, safeImage);
|
|
881
908
|
|
package/Rendering/OpenGL.js
CHANGED
|
@@ -16,6 +16,7 @@ import vtkOpenGLPolyDataMapper from './OpenGL/PolyDataMapper.js';
|
|
|
16
16
|
import vtkPolyDataMapper2D from './OpenGL/PolyDataMapper2D.js';
|
|
17
17
|
import vtkRenderer from './OpenGL/Renderer.js';
|
|
18
18
|
import vtkRenderWindow from './OpenGL/RenderWindow.js';
|
|
19
|
+
import './OpenGL/ScalarBarActor.js';
|
|
19
20
|
import vtkShader from './OpenGL/Shader.js';
|
|
20
21
|
import vtkShaderCache from './OpenGL/ShaderCache.js';
|
|
21
22
|
import vtkShaderProgram from './OpenGL/ShaderProgram.js';
|
|
@@ -20,15 +20,6 @@ var vtkDebugMacro = vtkDebugMacro$1; // the webgpu constants all show up as unde
|
|
|
20
20
|
// ----------------------------------------------------------------------------
|
|
21
21
|
|
|
22
22
|
var STATIC = {};
|
|
23
|
-
|
|
24
|
-
function requestMatches(req1, req2) {
|
|
25
|
-
if (req1.time !== req2.time) return false;
|
|
26
|
-
if (req1.format !== req2.format) return false;
|
|
27
|
-
if (req1.usage !== req2.usage) return false;
|
|
28
|
-
if (req1.hash !== req2.hash) return false;
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
23
|
var cellCounters = {
|
|
33
24
|
// easy, every input point becomes an output point
|
|
34
25
|
anythingToPoints: function anythingToPoints(numPoints, cellPts) {
|
|
@@ -363,44 +354,10 @@ function generateNormals(cellArray, primType, representation, inArray) {
|
|
|
363
354
|
|
|
364
355
|
function vtkWebGPUBufferManager(publicAPI, model) {
|
|
365
356
|
// Set our className
|
|
366
|
-
model.classHierarchy.push('vtkWebGPUBufferManager');
|
|
367
|
-
|
|
368
|
-
publicAPI.hasBuffer = function (req) {
|
|
369
|
-
if (req.source) {
|
|
370
|
-
// if a matching buffer already exists then return true
|
|
371
|
-
if (model.buffers.has(req.source)) {
|
|
372
|
-
var dabuffers = model.buffers.get(req.source);
|
|
373
|
-
|
|
374
|
-
for (var i = 0; i < dabuffers.length; i++) {
|
|
375
|
-
if (requestMatches(dabuffers[i].request, req)) {
|
|
376
|
-
return true;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
return false;
|
|
383
|
-
}; // we cache based on the passed in source, when the source is
|
|
384
|
-
// garbage collected then the cache entry is removed. If a source
|
|
385
|
-
// is not provided then the buffer is NOT cached and you are on your own
|
|
386
|
-
// if you want to share it etc
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
publicAPI.getBuffer = function (req) {
|
|
390
|
-
if (req.source) {
|
|
391
|
-
// if a matching buffer already exists then return it
|
|
392
|
-
if (model.buffers.has(req.source)) {
|
|
393
|
-
var dabuffers = model.buffers.get(req.source);
|
|
394
|
-
|
|
395
|
-
for (var i = 0; i < dabuffers.length; i++) {
|
|
396
|
-
if (requestMatches(dabuffers[i].request, req)) {
|
|
397
|
-
return dabuffers[i].buffer;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
} // if a dataArray is provided set the nativeArray
|
|
402
|
-
|
|
357
|
+
model.classHierarchy.push('vtkWebGPUBufferManager');
|
|
403
358
|
|
|
359
|
+
function _createBuffer(req) {
|
|
360
|
+
// if a dataArray is provided set the nativeArray
|
|
404
361
|
if (req.dataArray && !req.nativeArray) {
|
|
405
362
|
req.nativeArray = req.dataArray.getData();
|
|
406
363
|
} // create one
|
|
@@ -450,8 +407,7 @@ function vtkWebGPUBufferManager(publicAPI, model) {
|
|
|
450
407
|
scale: req.scale,
|
|
451
408
|
cellData: req.cellData,
|
|
452
409
|
cellOffset: req.cellOffset
|
|
453
|
-
});
|
|
454
|
-
|
|
410
|
+
});
|
|
455
411
|
buffer.createAndWrite(result.nativeArray, gpuUsage);
|
|
456
412
|
buffer.setStrideInBytes(vtkWebGPUTypes.getByteStrideFromBufferFormat(req.format));
|
|
457
413
|
buffer.setArrayInformation([{
|
|
@@ -482,29 +438,30 @@ function vtkWebGPUBufferManager(publicAPI, model) {
|
|
|
482
438
|
}]);
|
|
483
439
|
}
|
|
484
440
|
|
|
485
|
-
buffer.setSourceTime(req.time);
|
|
486
|
-
|
|
487
|
-
|
|
441
|
+
buffer.setSourceTime(req.time);
|
|
442
|
+
return buffer;
|
|
443
|
+
} // is the buffer already present?
|
|
488
444
|
|
|
489
|
-
if (req.source) {
|
|
490
|
-
if (!model.buffers.has(req.source)) {
|
|
491
|
-
model.buffers.set(req.source, []);
|
|
492
|
-
}
|
|
493
445
|
|
|
494
|
-
|
|
446
|
+
publicAPI.hasBuffer = function (req) {
|
|
447
|
+
if (req.owner) {
|
|
448
|
+
// if a matching buffer already exists then return true
|
|
449
|
+
var hash = req.time + req.format + req.usage + req.hash;
|
|
450
|
+
return model.device.hasCachedObject(req.owner, hash);
|
|
451
|
+
}
|
|
495
452
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
453
|
+
return false;
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
publicAPI.getBuffer = function (req) {
|
|
457
|
+
// if we have a source the get/create/cache the buffer
|
|
458
|
+
if (req.owner) {
|
|
459
|
+
// if a matching buffer already exists then return it
|
|
460
|
+
var hash = req.time + req.format + req.usage + req.hash;
|
|
461
|
+
return model.device.getCachedObject(req.owner, hash, _createBuffer, req);
|
|
505
462
|
}
|
|
506
463
|
|
|
507
|
-
return
|
|
464
|
+
return _createBuffer(req);
|
|
508
465
|
};
|
|
509
466
|
|
|
510
467
|
publicAPI.getFullScreenQuadBuffer = function () {
|
|
@@ -538,9 +495,7 @@ function extend(publicAPI, model) {
|
|
|
538
495
|
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
539
496
|
Object.assign(model, DEFAULT_VALUES, initialValues); // Object methods
|
|
540
497
|
|
|
541
|
-
obj(publicAPI, model);
|
|
542
|
-
|
|
543
|
-
model.buffers = new WeakMap();
|
|
498
|
+
obj(publicAPI, model);
|
|
544
499
|
setGet(publicAPI, model, ['device']);
|
|
545
500
|
vtkWebGPUBufferManager(publicAPI, model);
|
|
546
501
|
} // ----------------------------------------------------------------------------
|
|
@@ -89,6 +89,76 @@ function vtkWebGPUDevice(publicAPI, model) {
|
|
|
89
89
|
|
|
90
90
|
publicAPI.onSubmittedWorkDone = function () {
|
|
91
91
|
return model.handle.queue.onSubmittedWorkDone();
|
|
92
|
+
}; // The Device has an object cache that can be used to cache buffers,
|
|
93
|
+
// textures and other objects that can be shared. The basic approach is to
|
|
94
|
+
// call getCachedObject with a request and a create function. The request
|
|
95
|
+
// must have two fields a hash and an owner. The owner is what the weak
|
|
96
|
+
// map uses to hold onto the cached object. When the owner is deleted the
|
|
97
|
+
// cached object will be freed from the cache. The cache lookup just
|
|
98
|
+
// returns any entry that has a matching owner and hash. If a match isn't
|
|
99
|
+
// found then the create function is called with any extra arguments.
|
|
100
|
+
//
|
|
101
|
+
// For best memory management it is important that the owner be as close
|
|
102
|
+
// to the underlying object as possible. For example for a point data buffer
|
|
103
|
+
// you would want the actual vtkDataArray to be the owner, not the polydata
|
|
104
|
+
// or even worse the actor. As the points data array could be freed wihtout
|
|
105
|
+
// the polydata or actor being freed.
|
|
106
|
+
// is the object already cached?
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
publicAPI.hasCachedObject = function (owner, hash) {
|
|
110
|
+
if (!owner) {
|
|
111
|
+
return false;
|
|
112
|
+
} // if a matching request already exists then return true
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
if (model.objectCache.has(owner)) {
|
|
116
|
+
var objects = model.objectCache.get(owner);
|
|
117
|
+
|
|
118
|
+
for (var i = 0; i < objects.length; i++) {
|
|
119
|
+
if (hash === objects[i].hash) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return false;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
publicAPI.getCachedObject = function (owner, hash, creator) {
|
|
129
|
+
if (!owner || !hash) {
|
|
130
|
+
vtkErrorMacro('attempt to cache an object without an owner or hash');
|
|
131
|
+
return null;
|
|
132
|
+
} // if a matching request already exists then return the cached object
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
if (model.objectCache.has(owner)) {
|
|
136
|
+
var _objects = model.objectCache.get(owner);
|
|
137
|
+
|
|
138
|
+
for (var i = 0; i < _objects.length; i++) {
|
|
139
|
+
if (hash === _objects[i].hash) {
|
|
140
|
+
return _objects[i].object;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
} // otherwise create the object and cache it
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
for (var _len = arguments.length, args = new Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
|
|
147
|
+
args[_key - 3] = arguments[_key];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
var createdObject = creator.apply(void 0, args);
|
|
151
|
+
|
|
152
|
+
if (!model.objectCache.has(owner)) {
|
|
153
|
+
model.objectCache.set(owner, []);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
var objects = model.objectCache.get(owner);
|
|
157
|
+
objects.push({
|
|
158
|
+
hash: hash,
|
|
159
|
+
object: createdObject
|
|
160
|
+
});
|
|
161
|
+
return createdObject;
|
|
92
162
|
};
|
|
93
163
|
} // ----------------------------------------------------------------------------
|
|
94
164
|
// Object factory
|
|
@@ -110,7 +180,9 @@ function extend(publicAPI, model) {
|
|
|
110
180
|
|
|
111
181
|
obj(publicAPI, model);
|
|
112
182
|
setGet(publicAPI, model, ['handle']);
|
|
113
|
-
get(publicAPI, model, ['bufferManager', 'shaderCache', 'textureManager']);
|
|
183
|
+
get(publicAPI, model, ['bufferManager', 'shaderCache', 'textureManager']); // this is a cache, and a cache with GC pretty much means WeakMap
|
|
184
|
+
|
|
185
|
+
model.objectCache = new WeakMap();
|
|
114
186
|
model.shaderCache = vtkWebGPUShaderCache.newInstance();
|
|
115
187
|
model.shaderCache.setDevice(publicAPI);
|
|
116
188
|
model.bindGroupLayouts = [];
|
|
@@ -269,7 +269,7 @@ function vtkWebGPUImageMapper(publicAPI, model) {
|
|
|
269
269
|
publicAPI.updateBuffers = function (device) {
|
|
270
270
|
var treq = {
|
|
271
271
|
imageData: model.currentInput,
|
|
272
|
-
|
|
272
|
+
owner: model.currentInput.getPointData().getScalars()
|
|
273
273
|
};
|
|
274
274
|
var newTex = device.getTextureManager().getTexture(treq);
|
|
275
275
|
var tViews = model.helper.getTextureViews();
|
|
@@ -262,7 +262,8 @@ function vtkWebGPUPolyDataMapper(publicAPI, model) {
|
|
|
262
262
|
representation = Representation.WIREFRAME;
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
var vertexInput = model.primitives[primType].getVertexInput();
|
|
265
|
+
var vertexInput = model.primitives[primType].getVertexInput();
|
|
266
|
+
var hash = "R".concat(representation, "P").concat(primType); // hash = all things that can change the values on the buffer
|
|
266
267
|
// since mtimes are unique we can use
|
|
267
268
|
// - cells mtime - because cells drive how we pack
|
|
268
269
|
// - rep (point/wireframe/surface) - again because of packing
|
|
@@ -273,24 +274,23 @@ function vtkWebGPUPolyDataMapper(publicAPI, model) {
|
|
|
273
274
|
// - usage
|
|
274
275
|
// - packExtra - covered by format
|
|
275
276
|
// - prim type (vert/lines/polys/strips) - covered by cells mtime
|
|
276
|
-
|
|
277
|
-
var hash = cells.getMTime() + representation; // points
|
|
277
|
+
// points
|
|
278
278
|
|
|
279
279
|
var points = pd.getPoints();
|
|
280
280
|
|
|
281
281
|
if (points) {
|
|
282
282
|
var shift = model.WebGPUActor.getBufferShift(model.WebGPURenderer);
|
|
283
283
|
var buffRequest = {
|
|
284
|
-
|
|
284
|
+
owner: points,
|
|
285
|
+
usage: BufferUsage.PointArray,
|
|
286
|
+
format: 'float32x4',
|
|
287
|
+
time: Math.max(points.getMTime(), cells.getMTime(), model.WebGPUActor.getKeyMatricesTime().getMTime()),
|
|
288
|
+
hash: hash,
|
|
285
289
|
dataArray: points,
|
|
286
|
-
source: points,
|
|
287
290
|
cells: cells,
|
|
288
291
|
primitiveType: primType,
|
|
289
292
|
representation: representation,
|
|
290
|
-
time: Math.max(points.getMTime(), cells.getMTime(), model.WebGPUActor.getKeyMatricesTime().getMTime()),
|
|
291
293
|
shift: shift,
|
|
292
|
-
usage: BufferUsage.PointArray,
|
|
293
|
-
format: 'float32x4',
|
|
294
294
|
packExtra: true
|
|
295
295
|
};
|
|
296
296
|
var buff = device.getBufferManager().getBuffer(buffRequest);
|
|
@@ -305,19 +305,19 @@ function vtkWebGPUPolyDataMapper(publicAPI, model) {
|
|
|
305
305
|
if (usage === BufferUsage.Triangles || usage === BufferUsage.Strips) {
|
|
306
306
|
var normals = pd.getPointData().getNormals();
|
|
307
307
|
var _buffRequest = {
|
|
308
|
+
format: 'snorm8x4',
|
|
309
|
+
hash: hash,
|
|
308
310
|
cells: cells,
|
|
309
311
|
representation: representation,
|
|
310
312
|
primitiveType: primType,
|
|
311
|
-
format: 'snorm8x4',
|
|
312
313
|
packExtra: true,
|
|
313
314
|
shift: 0,
|
|
314
315
|
scale: 127
|
|
315
316
|
};
|
|
316
317
|
|
|
317
318
|
if (normals) {
|
|
318
|
-
_buffRequest.
|
|
319
|
+
_buffRequest.owner = normals;
|
|
319
320
|
_buffRequest.dataArray = normals;
|
|
320
|
-
_buffRequest.source = normals;
|
|
321
321
|
_buffRequest.time = Math.max(normals.getMTime(), cells.getMTime());
|
|
322
322
|
_buffRequest.usage = BufferUsage.PointArray;
|
|
323
323
|
|
|
@@ -325,9 +325,8 @@ function vtkWebGPUPolyDataMapper(publicAPI, model) {
|
|
|
325
325
|
|
|
326
326
|
vertexInput.addBuffer(_buff, ['normalMC']);
|
|
327
327
|
} else if (primType === PrimitiveTypes.Triangles) {
|
|
328
|
-
_buffRequest.
|
|
328
|
+
_buffRequest.owner = points;
|
|
329
329
|
_buffRequest.dataArray = points;
|
|
330
|
-
_buffRequest.source = points;
|
|
331
330
|
_buffRequest.time = Math.max(points.getMTime(), cells.getMTime());
|
|
332
331
|
_buffRequest.usage = BufferUsage.NormalsFromPoints;
|
|
333
332
|
|
|
@@ -356,15 +355,15 @@ function vtkWebGPUPolyDataMapper(publicAPI, model) {
|
|
|
356
355
|
}
|
|
357
356
|
|
|
358
357
|
var _buffRequest2 = {
|
|
359
|
-
|
|
358
|
+
owner: c,
|
|
359
|
+
usage: BufferUsage.PointArray,
|
|
360
|
+
format: 'unorm8x4',
|
|
361
|
+
time: Math.max(c.getMTime(), cells.getMTime(), points.getMTime()),
|
|
362
|
+
hash: hash + haveCellScalars,
|
|
360
363
|
dataArray: c,
|
|
361
|
-
source: c,
|
|
362
364
|
cells: cells,
|
|
363
365
|
primitiveType: primType,
|
|
364
366
|
representation: representation,
|
|
365
|
-
time: Math.max(c.getMTime(), cells.getMTime()),
|
|
366
|
-
usage: BufferUsage.PointArray,
|
|
367
|
-
format: 'unorm8x4',
|
|
368
367
|
cellData: haveCellScalars,
|
|
369
368
|
cellOffset: 0
|
|
370
369
|
};
|
|
@@ -390,15 +389,15 @@ function vtkWebGPUPolyDataMapper(publicAPI, model) {
|
|
|
390
389
|
|
|
391
390
|
if (tcoords && !edges) {
|
|
392
391
|
var _buffRequest3 = {
|
|
393
|
-
|
|
392
|
+
owner: tcoords,
|
|
393
|
+
usage: BufferUsage.PointArray,
|
|
394
|
+
format: 'float32x2',
|
|
395
|
+
time: Math.max(tcoords.getMTime(), cells.getMTime()),
|
|
396
|
+
hash: hash,
|
|
394
397
|
dataArray: tcoords,
|
|
395
|
-
source: tcoords,
|
|
396
398
|
cells: cells,
|
|
397
399
|
primitiveType: primType,
|
|
398
|
-
representation: representation
|
|
399
|
-
time: Math.max(tcoords.getMTime(), cells.getMTime()),
|
|
400
|
-
usage: BufferUsage.PointArray,
|
|
401
|
-
format: 'float32x2'
|
|
400
|
+
representation: representation
|
|
402
401
|
};
|
|
403
402
|
|
|
404
403
|
var _buff4 = device.getBufferManager().getBuffer(_buffRequest3);
|
|
@@ -433,7 +432,7 @@ function vtkWebGPUPolyDataMapper(publicAPI, model) {
|
|
|
433
432
|
var textures = actor.getTextures();
|
|
434
433
|
|
|
435
434
|
for (var i = 0; i < textures.length; i++) {
|
|
436
|
-
if (textures[i].getInputData()) {
|
|
435
|
+
if (textures[i].getInputData() || textures[i].getJsImageData() || textures[i].getCanvas()) {
|
|
437
436
|
newTextures.push(textures[i]);
|
|
438
437
|
}
|
|
439
438
|
|
|
@@ -446,14 +445,22 @@ function vtkWebGPUPolyDataMapper(publicAPI, model) {
|
|
|
446
445
|
|
|
447
446
|
for (var _i = 0; _i < newTextures.length; _i++) {
|
|
448
447
|
var srcTexture = newTextures[_i];
|
|
449
|
-
var treq = {
|
|
448
|
+
var treq = {
|
|
449
|
+
time: srcTexture.getMTime()
|
|
450
|
+
};
|
|
450
451
|
|
|
451
452
|
if (srcTexture.getInputData()) {
|
|
452
453
|
treq.imageData = srcTexture.getInputData();
|
|
453
|
-
treq.
|
|
454
|
+
treq.owner = treq.imageData.getPointData().getScalars();
|
|
454
455
|
} else if (srcTexture.getImage()) {
|
|
455
456
|
treq.image = srcTexture.getImage();
|
|
456
|
-
treq.
|
|
457
|
+
treq.owner = treq.image;
|
|
458
|
+
} else if (srcTexture.getJsImageData()) {
|
|
459
|
+
treq.jsImageData = srcTexture.getJsImageData();
|
|
460
|
+
treq.owner = treq.jsImageData;
|
|
461
|
+
} else if (srcTexture.getCanvas()) {
|
|
462
|
+
treq.canvas = srcTexture.getCanvas();
|
|
463
|
+
treq.owner = treq.canvas;
|
|
457
464
|
}
|
|
458
465
|
|
|
459
466
|
var newTex = model.device.getTextureManager().getTexture(treq);
|
|
@@ -67,8 +67,8 @@ function vtkWebGPUSphereMapper(publicAPI, model) {
|
|
|
67
67
|
primHelper.setNumberOfVertices(3 * numPoints);
|
|
68
68
|
var vertexInput = model.primitives[i].getVertexInput();
|
|
69
69
|
var buffRequest = {
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
owner: points,
|
|
71
|
+
hash: 'spm',
|
|
72
72
|
time: points.getMTime(),
|
|
73
73
|
usage: BufferUsage.RawVertex,
|
|
74
74
|
format: 'float32x3'
|
|
@@ -110,8 +110,8 @@ function vtkWebGPUSphereMapper(publicAPI, model) {
|
|
|
110
110
|
|
|
111
111
|
if (scales || defaultRadius !== model._lastRadius) {
|
|
112
112
|
buffRequest = {
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
owner: scales,
|
|
114
|
+
hash: 'spm',
|
|
115
115
|
time: scales ? pointData.getArray(model.renderable.getScaleArray()).getMTime() : 0,
|
|
116
116
|
usage: BufferUsage.RawVertex,
|
|
117
117
|
format: 'float32x2'
|
|
@@ -157,8 +157,8 @@ function vtkWebGPUSphereMapper(publicAPI, model) {
|
|
|
157
157
|
|
|
158
158
|
if (c) {
|
|
159
159
|
buffRequest = {
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
owner: c,
|
|
161
|
+
hash: 'spm',
|
|
162
162
|
time: c.getMTime(),
|
|
163
163
|
usage: BufferUsage.RawVertex,
|
|
164
164
|
format: 'unorm8x4'
|
|
@@ -89,8 +89,8 @@ function vtkWebGPUStickMapper(publicAPI, model) {
|
|
|
89
89
|
primHelper.setNumberOfVertices(12);
|
|
90
90
|
var vertexInput = model.primitives[i].getVertexInput();
|
|
91
91
|
var buffRequest = {
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
owner: points,
|
|
93
|
+
hash: 'stm',
|
|
94
94
|
time: points.getMTime(),
|
|
95
95
|
usage: BufferUsage.RawVertex,
|
|
96
96
|
format: 'float32x3'
|
|
@@ -125,8 +125,8 @@ function vtkWebGPUStickMapper(publicAPI, model) {
|
|
|
125
125
|
|
|
126
126
|
if (scales || defaultRadius !== model._lastRadius) {
|
|
127
127
|
buffRequest = {
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
owner: scales,
|
|
129
|
+
hash: 'stm',
|
|
130
130
|
time: scales ? pointData.getArray(model.renderable.getScaleArray()).getMTime() : 0,
|
|
131
131
|
usage: BufferUsage.RawVertex,
|
|
132
132
|
format: 'float32'
|
|
@@ -166,8 +166,8 @@ function vtkWebGPUStickMapper(publicAPI, model) {
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
buffRequest = {
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
owner: orientationArray,
|
|
170
|
+
hash: 'stm',
|
|
171
171
|
time: pointData.getArray(model.renderable.getOrientationArray()).getMTime(),
|
|
172
172
|
usage: BufferUsage.RawVertex,
|
|
173
173
|
format: 'float32x3'
|
|
@@ -209,8 +209,8 @@ function vtkWebGPUStickMapper(publicAPI, model) {
|
|
|
209
209
|
|
|
210
210
|
if (c) {
|
|
211
211
|
buffRequest = {
|
|
212
|
-
|
|
213
|
-
|
|
212
|
+
owner: c,
|
|
213
|
+
hash: 'stm',
|
|
214
214
|
time: c.getMTime(),
|
|
215
215
|
usage: BufferUsage.RawVertex,
|
|
216
216
|
format: 'unorm8x4'
|
|
@@ -21,7 +21,7 @@ function vtkWebGPUTexture(publicAPI, model) {
|
|
|
21
21
|
model.height = options.height;
|
|
22
22
|
model.depth = options.depth ? options.depth : 1;
|
|
23
23
|
var dimension = model.depth === 1 ? '2d' : '3d';
|
|
24
|
-
model.format = options.format ? options.format : '
|
|
24
|
+
model.format = options.format ? options.format : 'rgba8unorm';
|
|
25
25
|
/* eslint-disable no-undef */
|
|
26
26
|
|
|
27
27
|
/* eslint-disable no-bitwise */
|
|
@@ -47,7 +47,7 @@ function vtkWebGPUTexture(publicAPI, model) {
|
|
|
47
47
|
model.width = options.width;
|
|
48
48
|
model.height = options.height;
|
|
49
49
|
model.depth = options.depth ? options.depth : 1;
|
|
50
|
-
model.format = options.format ? options.format : '
|
|
50
|
+
model.format = options.format ? options.format : 'rgba8unorm';
|
|
51
51
|
/* eslint-disable no-undef */
|
|
52
52
|
|
|
53
53
|
/* eslint-disable no-bitwise */
|
|
@@ -60,6 +60,27 @@ function vtkWebGPUTexture(publicAPI, model) {
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
publicAPI.writeImageData = function (req) {
|
|
63
|
+
if (req.canvas) {
|
|
64
|
+
model.device.getHandle().queue.copyExternalImageToTexture({
|
|
65
|
+
source: req.canvas,
|
|
66
|
+
flipY: req.flip
|
|
67
|
+
}, {
|
|
68
|
+
texture: model.handle,
|
|
69
|
+
premultipliedAlpha: true
|
|
70
|
+
}, [model.width, model.height, model.depth]);
|
|
71
|
+
model.ready = true;
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (req.jsImageData && !req.nativeArray) {
|
|
76
|
+
req.width = req.jsImageData.width;
|
|
77
|
+
req.height = req.jsImageData.height;
|
|
78
|
+
req.depth = 1;
|
|
79
|
+
req.format = 'rgba8unorm';
|
|
80
|
+
req.flip = true;
|
|
81
|
+
req.nativeArray = req.jsImageData.data;
|
|
82
|
+
}
|
|
83
|
+
|
|
63
84
|
var tDetails = vtkWebGPUTypes.getDetailsFromTextureFormat(model.format);
|
|
64
85
|
var bufferBytesPerRow = model.width * tDetails.stride;
|
|
65
86
|
|
|
@@ -5,26 +5,15 @@ import vtkWebGPUTexture from './Texture.js';
|
|
|
5
5
|
var VtkDataTypes = vtkDataArray.VtkDataTypes; // ----------------------------------------------------------------------------
|
|
6
6
|
// Global methods
|
|
7
7
|
// ----------------------------------------------------------------------------
|
|
8
|
-
|
|
9
|
-
function requestMatches(req1, req2) {
|
|
10
|
-
if (req1.time !== req2.time) return false;
|
|
11
|
-
if (req1.nativeArray !== req2.nativeArray) return false;
|
|
12
|
-
if (req1.format !== req2.format) return false;
|
|
13
|
-
return true;
|
|
14
|
-
} // ----------------------------------------------------------------------------
|
|
8
|
+
// ----------------------------------------------------------------------------
|
|
15
9
|
// vtkWebGPUTextureManager methods
|
|
16
10
|
// ----------------------------------------------------------------------------
|
|
17
11
|
|
|
18
|
-
|
|
19
12
|
function vtkWebGPUTextureManager(publicAPI, model) {
|
|
20
13
|
// Set our className
|
|
21
|
-
model.classHierarchy.push('vtkWebGPUTextureManager'); //
|
|
22
|
-
// - source, this is what owns the data and when it does away
|
|
23
|
-
// the data should be freed
|
|
24
|
-
// - imageData - when provided use as the source of the data
|
|
25
|
-
//
|
|
14
|
+
model.classHierarchy.push('vtkWebGPUTextureManager'); // fills in request values based on what is missing/provided
|
|
26
15
|
|
|
27
|
-
|
|
16
|
+
function _fillRequest(req) {
|
|
28
17
|
// fill in values based on imageData if the request has it
|
|
29
18
|
if (req.imageData) {
|
|
30
19
|
req.dataArray = req.imageData.getPointData().getScalars();
|
|
@@ -75,59 +64,71 @@ function vtkWebGPUTextureManager(publicAPI, model) {
|
|
|
75
64
|
|
|
76
65
|
|
|
77
66
|
if (req.image) {
|
|
78
|
-
req.time = 0;
|
|
79
67
|
req.width = req.image.width;
|
|
80
68
|
req.height = req.image.height;
|
|
81
69
|
req.depth = 1;
|
|
82
70
|
req.format = 'rgba8unorm';
|
|
71
|
+
} // fill in based on js imageData
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
if (req.jsImageData) {
|
|
75
|
+
req.width = req.jsImageData.width;
|
|
76
|
+
req.height = req.jsImageData.height;
|
|
77
|
+
req.depth = 1;
|
|
78
|
+
req.format = 'rgba8unorm';
|
|
79
|
+
req.flip = true;
|
|
80
|
+
req.nativeArray = req.jsImageData.data;
|
|
83
81
|
}
|
|
84
82
|
|
|
85
|
-
if (req.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
if (req.canvas) {
|
|
84
|
+
req.width = req.canvas.width;
|
|
85
|
+
req.height = req.canvas.height;
|
|
86
|
+
req.depth = 1;
|
|
87
|
+
req.format = 'rgba8unorm';
|
|
88
|
+
req.flip = true;
|
|
89
|
+
/* eslint-disable no-undef */
|
|
90
|
+
|
|
91
|
+
/* eslint-disable no-bitwise */
|
|
89
92
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
}
|
|
93
|
+
req.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;
|
|
94
|
+
/* eslint-enable no-undef */
|
|
95
|
+
|
|
96
|
+
/* eslint-enable no-bitwise */
|
|
96
97
|
}
|
|
98
|
+
} // create a texture (used by getTexture)
|
|
97
99
|
|
|
100
|
+
|
|
101
|
+
function _createTexture(req) {
|
|
98
102
|
var newTex = vtkWebGPUTexture.newInstance();
|
|
99
103
|
newTex.create(model.device, {
|
|
100
104
|
width: req.width,
|
|
101
105
|
height: req.height,
|
|
102
106
|
depth: req.depth,
|
|
103
|
-
format: req.format
|
|
107
|
+
format: req.format,
|
|
108
|
+
usage: req.usage
|
|
104
109
|
}); // fill the texture if we have data
|
|
105
110
|
|
|
106
|
-
if (req.nativeArray || req.image) {
|
|
111
|
+
if (req.nativeArray || req.image || req.canvas) {
|
|
107
112
|
newTex.writeImageData(req);
|
|
108
|
-
}
|
|
109
|
-
// We create a new req that only has the fields required for
|
|
110
|
-
// a comparison to avoid GC cycles
|
|
113
|
+
}
|
|
111
114
|
|
|
115
|
+
return newTex;
|
|
116
|
+
} // get a texture or create it if not cached.
|
|
117
|
+
// this is the main entry point
|
|
112
118
|
|
|
113
|
-
if (req.source) {
|
|
114
|
-
if (!model.textures.has(req.source)) {
|
|
115
|
-
model.textures.set(req.source, []);
|
|
116
|
-
}
|
|
117
119
|
|
|
118
|
-
|
|
120
|
+
publicAPI.getTexture = function (req) {
|
|
121
|
+
// if we have a source the get/create/cache the texture
|
|
122
|
+
if (req.owner) {
|
|
123
|
+
// fill out the req time and format based on imageData/image
|
|
124
|
+
_fillRequest(req); // if a matching texture already exists then return it
|
|
125
|
+
|
|
119
126
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
time: req.time,
|
|
123
|
-
nativeArray: req.nativeArray,
|
|
124
|
-
format: req.format
|
|
125
|
-
},
|
|
126
|
-
texture: newTex
|
|
127
|
-
});
|
|
127
|
+
var hash = req.time + req.format;
|
|
128
|
+
return model.device.getCachedObject(req.owner, hash, _createTexture, req);
|
|
128
129
|
}
|
|
129
130
|
|
|
130
|
-
return
|
|
131
|
+
return _createTexture(req);
|
|
131
132
|
};
|
|
132
133
|
} // ----------------------------------------------------------------------------
|
|
133
134
|
// Object factory
|
|
@@ -135,7 +136,6 @@ function vtkWebGPUTextureManager(publicAPI, model) {
|
|
|
135
136
|
|
|
136
137
|
|
|
137
138
|
var DEFAULT_VALUES = {
|
|
138
|
-
textures: null,
|
|
139
139
|
handle: null,
|
|
140
140
|
device: null
|
|
141
141
|
}; // ----------------------------------------------------------------------------
|
|
@@ -144,9 +144,7 @@ function extend(publicAPI, model) {
|
|
|
144
144
|
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
145
145
|
Object.assign(model, DEFAULT_VALUES, initialValues); // Object methods
|
|
146
146
|
|
|
147
|
-
macro.obj(publicAPI, model);
|
|
148
|
-
|
|
149
|
-
model.textures = new WeakMap();
|
|
147
|
+
macro.obj(publicAPI, model);
|
|
150
148
|
macro.setGet(publicAPI, model, ['device']);
|
|
151
149
|
vtkWebGPUTextureManager(publicAPI, model);
|
|
152
150
|
} // ----------------------------------------------------------------------------
|
|
@@ -259,20 +259,19 @@ function vtkWebGPUVolumePass(publicAPI, model) {
|
|
|
259
259
|
publicAPI.renderDepthBounds = function (renNode, viewNode) {
|
|
260
260
|
publicAPI.updateDepthPolyData(renNode);
|
|
261
261
|
var pd = model._boundsPoly;
|
|
262
|
-
var cells = pd.getPolys();
|
|
263
|
-
var hash = cells.getMTime(); // points
|
|
262
|
+
var cells = pd.getPolys(); // points
|
|
264
263
|
|
|
265
264
|
var points = pd.getPoints();
|
|
266
265
|
var buffRequest = {
|
|
267
|
-
|
|
266
|
+
owner: points,
|
|
267
|
+
usage: BufferUsage.PointArray,
|
|
268
|
+
format: 'float32x4',
|
|
269
|
+
time: Math.max(points.getMTime(), cells.getMTime()),
|
|
270
|
+
hash: 'vp',
|
|
268
271
|
dataArray: points,
|
|
269
|
-
source: points,
|
|
270
272
|
cells: cells,
|
|
271
273
|
primitiveType: PrimitiveTypes.Triangles,
|
|
272
274
|
representation: Representation.SURFACE,
|
|
273
|
-
time: Math.max(points.getMTime(), cells.getMTime()),
|
|
274
|
-
usage: BufferUsage.PointArray,
|
|
275
|
-
format: 'float32x4',
|
|
276
275
|
packExtra: true
|
|
277
276
|
};
|
|
278
277
|
var buff = viewNode.getDevice().getBufferManager().getBuffer(buffRequest);
|
package/Rendering/WebGPU.js
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
import vtkRenderWindow from './WebGPU/RenderWindow.js';
|
|
2
|
+
import './WebGPU/Actor.js';
|
|
3
|
+
import './WebGPU/Camera.js';
|
|
4
|
+
import './WebGPU/ForwardPass.js';
|
|
5
|
+
import './WebGPU/Glyph3DMapper.js';
|
|
6
|
+
import './WebGPU/HardwareSelector.js';
|
|
7
|
+
import './WebGPU/ImageMapper.js';
|
|
8
|
+
import './WebGPU/ImageSlice.js';
|
|
9
|
+
import './WebGPU/PixelSpaceCallbackMapper.js';
|
|
10
|
+
import './WebGPU/PolyDataMapper.js';
|
|
11
|
+
import './WebGPU/Renderer.js';
|
|
12
|
+
import './WebGPU/ScalarBarActor.js';
|
|
13
|
+
import './WebGPU/SphereMapper.js';
|
|
14
|
+
import './WebGPU/StickMapper.js';
|
|
15
|
+
import './WebGPU/Texture.js';
|
|
16
|
+
import './WebGPU/ViewNodeFactory.js';
|
|
17
|
+
import './WebGPU/Volume.js';
|
|
2
18
|
|
|
3
19
|
var WebGPU = {
|
|
4
20
|
vtkRenderWindow: vtkRenderWindow
|