@vitessce/spatial-accelerated 3.8.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/LICENSE +21 -0
- package/dist/index.js +52925 -0
- package/dist-tsc/SpatialWrapper.d.ts +2 -0
- package/dist-tsc/SpatialWrapper.d.ts.map +1 -0
- package/dist-tsc/SpatialWrapper.js +45 -0
- package/dist-tsc/VolumeDataManager.d.ts +170 -0
- package/dist-tsc/VolumeDataManager.d.ts.map +1 -0
- package/dist-tsc/VolumeDataManager.js +1273 -0
- package/dist-tsc/VolumeDataManager.test.d.ts +2 -0
- package/dist-tsc/VolumeDataManager.test.d.ts.map +1 -0
- package/dist-tsc/VolumeDataManager.test.js +164 -0
- package/dist-tsc/VolumeRenderManager.d.ts +265 -0
- package/dist-tsc/VolumeRenderManager.d.ts.map +1 -0
- package/dist-tsc/VolumeRenderManager.js +396 -0
- package/dist-tsc/VolumeShader.d.ts +262 -0
- package/dist-tsc/VolumeShader.d.ts.map +1 -0
- package/dist-tsc/VolumeShader.js +73 -0
- package/dist-tsc/VolumeView.d.ts +2 -0
- package/dist-tsc/VolumeView.d.ts.map +1 -0
- package/dist-tsc/VolumeView.js +521 -0
- package/dist-tsc/index.d.ts +2 -0
- package/dist-tsc/index.d.ts.map +1 -0
- package/dist-tsc/index.js +1 -0
- package/dist-tsc/shaders/GaussianFragmentShader.d.ts +2 -0
- package/dist-tsc/shaders/GaussianFragmentShader.d.ts.map +1 -0
- package/dist-tsc/shaders/GaussianFragmentShader.js +242 -0
- package/dist-tsc/shaders/GaussianVertexShader.d.ts +2 -0
- package/dist-tsc/shaders/GaussianVertexShader.d.ts.map +1 -0
- package/dist-tsc/shaders/GaussianVertexShader.js +51 -0
- package/dist-tsc/shaders/VolumeFragmentShader.d.ts +2 -0
- package/dist-tsc/shaders/VolumeFragmentShader.d.ts.map +1 -0
- package/dist-tsc/shaders/VolumeFragmentShader.js +1817 -0
- package/dist-tsc/shaders/VolumeVertexShader.d.ts +2 -0
- package/dist-tsc/shaders/VolumeVertexShader.d.ts.map +1 -0
- package/dist-tsc/shaders/VolumeVertexShader.js +110 -0
- package/package.json +63 -0
- package/src/SpatialWrapper.js +60 -0
- package/src/VolumeDataManager.js +1515 -0
- package/src/VolumeDataManager.test.js +180 -0
- package/src/VolumeRenderManager.js +589 -0
- package/src/VolumeShader.js +74 -0
- package/src/VolumeView.js +651 -0
- package/src/index.js +1 -0
- package/src/shaders/GaussianFragmentShader.js +243 -0
- package/src/shaders/GaussianVertexShader.js +52 -0
- package/src/shaders/VolumeFragmentShader.js +1818 -0
- package/src/shaders/VolumeVertexShader.js +111 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
import { Vector2, UniformsUtils, } from 'three';
|
|
3
|
+
import { CoordinationType } from '@vitessce/constants-internal';
|
|
4
|
+
import { log, atLeastLogLevel, LogLevel } from '@vitessce/globals';
|
|
5
|
+
import { VolumeShader } from './VolumeShader.js';
|
|
6
|
+
function logWithColor(message) {
|
|
7
|
+
if (atLeastLogLevel(LogLevel.DEBUG)) {
|
|
8
|
+
console.warn(`%cRM: ${message}`, 'background: orange; color: white; padding: 2px; border-radius: 3px;');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Normalize a value based on the volume's min/max range
|
|
13
|
+
* @param {number} value - Value to normalize
|
|
14
|
+
* @param {Array} minMax - [min, max] values of the volume
|
|
15
|
+
* @returns {number} Normalized value
|
|
16
|
+
*/
|
|
17
|
+
function normalizeValue(value, minMax) {
|
|
18
|
+
return value / minMax[1];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Manages the volume rendering state, shader setup, and uniform management
|
|
22
|
+
* Serves as a replacement for many functions from three-utils.js
|
|
23
|
+
*/
|
|
24
|
+
export class VolumeRenderManager {
|
|
25
|
+
constructor() {
|
|
26
|
+
logWithColor('Initializing VolumeRenderManager');
|
|
27
|
+
// Rendering settings
|
|
28
|
+
this.uniforms = null;
|
|
29
|
+
this.shader = null;
|
|
30
|
+
this.meshScale = [1, 1, 1];
|
|
31
|
+
this.geometrySize = [1, 1, 1];
|
|
32
|
+
this.boxSize = [1, 1, 1];
|
|
33
|
+
this.zarrInit = false;
|
|
34
|
+
// Channel and texture state
|
|
35
|
+
this.channelsVisible = [];
|
|
36
|
+
this.channelTargetC = [];
|
|
37
|
+
this.zarrStoreNumResolutions = null;
|
|
38
|
+
this.channelMaxResolutionIndex = [];
|
|
39
|
+
this.colors = [];
|
|
40
|
+
this.contrastLimits = [];
|
|
41
|
+
this.layerTransparency = 1.0;
|
|
42
|
+
this.xSlice = new Vector2(-1, 100000);
|
|
43
|
+
this.ySlice = new Vector2(-1, 100000);
|
|
44
|
+
this.zSlice = new Vector2(-1, 100000);
|
|
45
|
+
this.originalScale = [1, 1, 1];
|
|
46
|
+
this.physicalDimensions = [1, 1, 1]; // can be used later, currently our props scale by pixel
|
|
47
|
+
this.maxResolution = [1, 1, 1];
|
|
48
|
+
this.maxRange = 255;
|
|
49
|
+
this.maxRangeSet = false;
|
|
50
|
+
// Additional state
|
|
51
|
+
// this.mrt = null; // Single MRT reference
|
|
52
|
+
// Initialize shader
|
|
53
|
+
this.initializeShader();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Initialize shader and uniform objects
|
|
57
|
+
*/
|
|
58
|
+
initializeShader() {
|
|
59
|
+
logWithColor('Initializing shader');
|
|
60
|
+
this.shader = VolumeShader;
|
|
61
|
+
this.uniforms = UniformsUtils.clone(this.shader.uniforms);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Extract rendering settings from coordination props
|
|
65
|
+
* @param {Object} props - Component props
|
|
66
|
+
* @returns {Object} Extracted rendering settings
|
|
67
|
+
*/
|
|
68
|
+
extractRenderingSettingsFromProps(props) {
|
|
69
|
+
logWithColor('Extracting rendering settings from props');
|
|
70
|
+
// log.debug('props', props);
|
|
71
|
+
// log.debug('props.imageChannelCoordination', props.imageChannelCoordination[0]['A']);
|
|
72
|
+
const { images = {}, imageLayerScopes = [], imageLayerCoordination = [{}], imageChannelScopesByLayer = {}, imageChannelCoordination = [{}], spatialRenderingMode, } = props;
|
|
73
|
+
const layerScope = imageLayerScopes[0];
|
|
74
|
+
if (!layerScope) {
|
|
75
|
+
return {
|
|
76
|
+
valid: false,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const channelScopes = imageChannelScopesByLayer[layerScope];
|
|
80
|
+
const layerCoordination = imageLayerCoordination[0][layerScope];
|
|
81
|
+
const channelCoordination = imageChannelCoordination[0][layerScope];
|
|
82
|
+
const data = images[layerScope]?.image?.instance?.getData();
|
|
83
|
+
if (!data) {
|
|
84
|
+
return {
|
|
85
|
+
valid: false,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (!channelCoordination[channelScopes?.[0]][CoordinationType.SPATIAL_CHANNEL_WINDOW]) {
|
|
89
|
+
// We don't want to initialize with a null spatialChannelWindow,
|
|
90
|
+
// since down below we use the default value of [0, 255], but we may have a Uint16 image.
|
|
91
|
+
// This will cause the sliders to not affect the contrast limits until below 255,
|
|
92
|
+
// but their range will be much larger (e.g., 0-65535).
|
|
93
|
+
// TODO(mark): the defaults should be set based on the image dtype.
|
|
94
|
+
// TODO(mark): wait for all channel IQR ranges to be computed before initializing,
|
|
95
|
+
// as we do not want this.maxRange to be incorrect.
|
|
96
|
+
return {
|
|
97
|
+
valid: false,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
const imageWrapperInstance = images[layerScope].image.instance;
|
|
101
|
+
const is3dMode = spatialRenderingMode === '3D';
|
|
102
|
+
const isRgb = layerCoordination[CoordinationType.PHOTOMETRIC_INTERPRETATION] === 'RGB';
|
|
103
|
+
const visible = layerCoordination[CoordinationType.SPATIAL_LAYER_VISIBLE];
|
|
104
|
+
const layerTransparency = layerCoordination[CoordinationType.SPATIAL_LAYER_OPACITY];
|
|
105
|
+
// Extract colors
|
|
106
|
+
const colors = isRgb ? ([
|
|
107
|
+
[255, 0, 0],
|
|
108
|
+
[0, 255, 0],
|
|
109
|
+
[0, 0, 255],
|
|
110
|
+
]) : channelScopes.map(cScope => (channelCoordination[cScope][CoordinationType.SPATIAL_CHANNEL_COLOR]));
|
|
111
|
+
// Extract contrast limits
|
|
112
|
+
const contrastLimits = isRgb ? ([
|
|
113
|
+
[0, 255],
|
|
114
|
+
[0, 255],
|
|
115
|
+
[0, 255],
|
|
116
|
+
]) : channelScopes.map(cScope => (channelCoordination[cScope][CoordinationType.SPATIAL_CHANNEL_WINDOW]
|
|
117
|
+
|| ([0, 255])));
|
|
118
|
+
if (!this.maxRangeSet) {
|
|
119
|
+
this.maxRange = Math.max(...contrastLimits.map(limit => limit[1]));
|
|
120
|
+
this.maxRangeSet = true;
|
|
121
|
+
}
|
|
122
|
+
// Extract channel visibility
|
|
123
|
+
const channelsVisible = isRgb ? ([
|
|
124
|
+
visible && true,
|
|
125
|
+
visible && true,
|
|
126
|
+
visible && true,
|
|
127
|
+
]) : channelScopes.map(cScope => (visible && channelCoordination[cScope][CoordinationType.SPATIAL_CHANNEL_VISIBLE]));
|
|
128
|
+
// Extract channel target indices
|
|
129
|
+
const channelTargetC = isRgb ? ([
|
|
130
|
+
visible && true,
|
|
131
|
+
visible && true,
|
|
132
|
+
visible && true,
|
|
133
|
+
]) : channelScopes.map(cScope => (visible && imageWrapperInstance.getChannelIndex(channelCoordination[cScope][CoordinationType.SPATIAL_TARGET_C])));
|
|
134
|
+
// Get max resolution index
|
|
135
|
+
const channelMaxResolutionIndex = isRgb ? ([
|
|
136
|
+
visible && null,
|
|
137
|
+
visible && null,
|
|
138
|
+
visible && null,
|
|
139
|
+
]) : channelScopes.map(cScope => (channelCoordination[cScope][CoordinationType.SPATIAL_MAX_RESOLUTION]));
|
|
140
|
+
// Get slice planes
|
|
141
|
+
let xSlice = layerCoordination[CoordinationType.SPATIAL_SLICE_X];
|
|
142
|
+
let ySlice = layerCoordination[CoordinationType.SPATIAL_SLICE_Y];
|
|
143
|
+
let zSlice = layerCoordination[CoordinationType.SPATIAL_SLICE_Z];
|
|
144
|
+
xSlice = xSlice !== null ? xSlice : new Vector2(-1, 100000);
|
|
145
|
+
ySlice = ySlice !== null ? ySlice : new Vector2(-1, 100000);
|
|
146
|
+
zSlice = zSlice !== null ? zSlice : new Vector2(-1, 100000);
|
|
147
|
+
const allChannels = images[layerScope].image.loaders[0].channels;
|
|
148
|
+
return {
|
|
149
|
+
valid: true,
|
|
150
|
+
channelsVisible,
|
|
151
|
+
allChannels,
|
|
152
|
+
channelTargetC,
|
|
153
|
+
channelMaxResolutionIndex,
|
|
154
|
+
data,
|
|
155
|
+
colors,
|
|
156
|
+
contrastLimits,
|
|
157
|
+
is3dMode,
|
|
158
|
+
layerTransparency,
|
|
159
|
+
xSlice,
|
|
160
|
+
ySlice,
|
|
161
|
+
zSlice,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Update the render settings from the given props
|
|
166
|
+
* @param {Object} props - Component props
|
|
167
|
+
* @returns {boolean} True if settings were successfully updated
|
|
168
|
+
*/
|
|
169
|
+
updateFromProps(props) {
|
|
170
|
+
logWithColor('Updating from props');
|
|
171
|
+
const settings = this.extractRenderingSettingsFromProps(props);
|
|
172
|
+
if (!settings.valid) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
// Store the extracted settings
|
|
176
|
+
this.channelsVisible = settings.channelsVisible;
|
|
177
|
+
this.channelTargetC = settings.channelTargetC;
|
|
178
|
+
this.channelMaxResolutionIndex = settings.channelMaxResolutionIndex;
|
|
179
|
+
this.colors = settings.colors;
|
|
180
|
+
this.contrastLimits = settings.contrastLimits;
|
|
181
|
+
this.renderingMode = settings.renderingMode;
|
|
182
|
+
this.layerTransparency = settings.layerTransparency;
|
|
183
|
+
this.xSlice = settings.xSlice;
|
|
184
|
+
this.ySlice = settings.ySlice;
|
|
185
|
+
this.zSlice = settings.zSlice;
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Update the rendering based on the current volume data from the data manager
|
|
190
|
+
* @param {object} volumeDataManagerProps - Params derived from the volume data manager
|
|
191
|
+
* @returns {Object|null} Updated rendering settings or null if rendering is not possible
|
|
192
|
+
*/
|
|
193
|
+
updateRendering({ zarrStoreShapes, originalScaleXYZ, physicalDimensionsXYZ, maxResolutionXYZ, boxDimensionsXYZ, normalizedScaleXYZ, bcTHREE, ptTHREE, }) {
|
|
194
|
+
logWithColor('Updating rendering');
|
|
195
|
+
// Check if we have at least one visible channel
|
|
196
|
+
const visibleChannelIndex = this.channelTargetC.findIndex((channel, idx) => this.channelsVisible[idx]);
|
|
197
|
+
// if (visibleChannelIndex === -1) {
|
|
198
|
+
// return null;
|
|
199
|
+
// }
|
|
200
|
+
// Instead of getting dimensions from a volume, get from zarrStore
|
|
201
|
+
if (!Array.isArray(zarrStoreShapes) || zarrStoreShapes.length === 0) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
// Get dimensions from zarrStore
|
|
205
|
+
const shape = zarrStoreShapes[0];
|
|
206
|
+
// Use the highest resolution shape (shape at index 0)
|
|
207
|
+
// Shape format is typically [t, c, z, y, x]
|
|
208
|
+
const dimensions = {
|
|
209
|
+
xLength: shape[4] || 1,
|
|
210
|
+
yLength: shape[3] || 1,
|
|
211
|
+
zLength: shape[2] || 1,
|
|
212
|
+
};
|
|
213
|
+
// Collect settings for active channels
|
|
214
|
+
const texturesList = [];
|
|
215
|
+
const colorsSave = [];
|
|
216
|
+
const contrastLimitsList = [];
|
|
217
|
+
// ', this);
|
|
218
|
+
// log.debug('this.channelsVisible', this.channelsVisible);
|
|
219
|
+
// log.debug('this.channelTargetC', this.channelTargetC);
|
|
220
|
+
// log.debug('this.colors', this.colors);
|
|
221
|
+
// log.debug('this.contrastLimits', this.contrastLimits);
|
|
222
|
+
this.channelTargetC.forEach((channel, id) => {
|
|
223
|
+
// log.debug('channel', channel);
|
|
224
|
+
// log.debug('id', id);
|
|
225
|
+
// log.debug('this.channelsVisible', this.channelsVisible);
|
|
226
|
+
if (this.channelsVisible[id] || true) { // TODO: remove true
|
|
227
|
+
// Since we don't have volume-based minMax, use fixed values
|
|
228
|
+
// or get them from your brick cache metadata if available
|
|
229
|
+
// big TODO
|
|
230
|
+
const max = this.maxRange ? this.maxRange : 255;
|
|
231
|
+
const minMax = [0, max]; // Default values
|
|
232
|
+
// log.debug('this.colors[id]', this.colors[id]);
|
|
233
|
+
// log.debug('this.channelsVisible[id]', this.channelsVisible[id]);
|
|
234
|
+
colorsSave.push([
|
|
235
|
+
this.colors[id][0] / 255,
|
|
236
|
+
this.colors[id][1] / 255,
|
|
237
|
+
this.colors[id][2] / 255,
|
|
238
|
+
this.channelsVisible[id] ? 1.0 : 0.0,
|
|
239
|
+
]);
|
|
240
|
+
log.debug('colorsSave', colorsSave);
|
|
241
|
+
if (this.contrastLimits[id][0] === 0 && this.contrastLimits[id][1] === 255) {
|
|
242
|
+
contrastLimitsList.push([
|
|
243
|
+
normalizeValue(minMax[0], minMax),
|
|
244
|
+
normalizeValue(minMax[1], minMax),
|
|
245
|
+
]);
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
contrastLimitsList.push([
|
|
249
|
+
normalizeValue(this.contrastLimits[id][0], minMax),
|
|
250
|
+
normalizeValue(this.contrastLimits[id][1], minMax),
|
|
251
|
+
]);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
if (!this.zarrInit) {
|
|
256
|
+
// Initialize from zarrStore data
|
|
257
|
+
this.originalScale = originalScaleXYZ;
|
|
258
|
+
this.physicalDimensions = physicalDimensionsXYZ;
|
|
259
|
+
this.maxResolution = maxResolutionXYZ;
|
|
260
|
+
const scaledResolution = boxDimensionsXYZ;
|
|
261
|
+
this.normalizedScale = normalizedScaleXYZ;
|
|
262
|
+
this.meshScale = [
|
|
263
|
+
this.originalScale[0] / this.originalScale[0],
|
|
264
|
+
this.originalScale[1] / this.originalScale[0],
|
|
265
|
+
this.originalScale[2] / this.originalScale[0],
|
|
266
|
+
];
|
|
267
|
+
this.geometrySize = scaledResolution;
|
|
268
|
+
this.boxSize = scaledResolution;
|
|
269
|
+
log.debug('this.boxSize', this.boxSize);
|
|
270
|
+
log.debug('this.geometrySize', this.geometrySize);
|
|
271
|
+
log.debug('this.meshScale', this.meshScale);
|
|
272
|
+
log.debug('this.originalScale', this.originalScale);
|
|
273
|
+
log.debug('this.physicalDimensions', this.physicalDimensions);
|
|
274
|
+
log.debug('this.maxResolution', this.maxResolution);
|
|
275
|
+
log.debug('scaledResolution', scaledResolution);
|
|
276
|
+
this.zarrInit = true;
|
|
277
|
+
}
|
|
278
|
+
// Update shader uniforms
|
|
279
|
+
this.updateUniforms(texturesList, dimensions, // Pass dimensions object instead of volume
|
|
280
|
+
this.renderingMode, contrastLimitsList, colorsSave, this.layerTransparency, this.xSlice, this.ySlice, this.zSlice, bcTHREE, ptTHREE);
|
|
281
|
+
return {
|
|
282
|
+
uniforms: this.uniforms,
|
|
283
|
+
shader: this.shader,
|
|
284
|
+
meshScale: this.meshScale,
|
|
285
|
+
geometrySize: this.geometrySize,
|
|
286
|
+
boxSize: this.boxSize,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Update shader uniforms with current rendering values
|
|
291
|
+
* @param {Array} textures - List of 3D textures
|
|
292
|
+
* @param {Object} dimensions - Dimensions object
|
|
293
|
+
* @param {number} renderstyle - Rendering mode value
|
|
294
|
+
* @param {Array} contrastLimits - List of contrast limits for each channel
|
|
295
|
+
* @param {Array} colors - List of colors for each channel
|
|
296
|
+
* @param {number} layerTransparency - Overall transparency value
|
|
297
|
+
* @param {Vector2} xSlice - X clipping plane
|
|
298
|
+
* @param {Vector2} ySlice - Y clipping plane
|
|
299
|
+
* @param {Vector2} zSlice - Z clipping plane
|
|
300
|
+
*/
|
|
301
|
+
updateUniforms(textures, dimensions, renderstyle, contrastLimits, colors, layerTransparency, xSlice, ySlice, zSlice, brickCacheTexture, pageTableTexture) {
|
|
302
|
+
logWithColor('Updating uniforms');
|
|
303
|
+
// Set base uniforms
|
|
304
|
+
this.uniforms.boxSize.value.set(this.boxSize[0], this.boxSize[1], this.boxSize[2]);
|
|
305
|
+
// Set texture uniforms
|
|
306
|
+
this.uniforms.brickCacheTex.value = brickCacheTexture;
|
|
307
|
+
this.uniforms.pageTableTex.value = pageTableTexture;
|
|
308
|
+
// Set general rendering parameters
|
|
309
|
+
this.uniforms.near.value = 0.1;
|
|
310
|
+
this.uniforms.far.value = 3000; // TODO: check this
|
|
311
|
+
this.uniforms.opacity.value = layerTransparency;
|
|
312
|
+
this.uniforms.volumeCount.value = textures.length;
|
|
313
|
+
// Set size and scale parameters using dimensions object
|
|
314
|
+
this.uniforms.u_size.value.set(dimensions.xLength, dimensions.yLength, dimensions.zLength);
|
|
315
|
+
this.uniforms.u_window_size.value.set(0, 0);
|
|
316
|
+
this.uniforms.u_vol_scale.value.set(1.0 / dimensions.xLength, 1.0 / dimensions.yLength, 1.0 / dimensions.zLength * 2.0);
|
|
317
|
+
// Set contrast limits (up to 6 channels)
|
|
318
|
+
this.uniforms.clim0.value.set(contrastLimits.length > 0 ? contrastLimits[0][0] : null, contrastLimits.length > 0 ? contrastLimits[0][1] : null);
|
|
319
|
+
this.uniforms.clim1.value.set(contrastLimits.length > 1 ? contrastLimits[1][0] : null, contrastLimits.length > 1 ? contrastLimits[1][1] : null);
|
|
320
|
+
this.uniforms.clim2.value.set(contrastLimits.length > 2 ? contrastLimits[2][0] : null, contrastLimits.length > 2 ? contrastLimits[2][1] : null);
|
|
321
|
+
this.uniforms.clim3.value.set(contrastLimits.length > 3 ? contrastLimits[3][0] : null, contrastLimits.length > 3 ? contrastLimits[3][1] : null);
|
|
322
|
+
this.uniforms.clim4.value.set(contrastLimits.length > 4 ? contrastLimits[4][0] : null, contrastLimits.length > 4 ? contrastLimits[4][1] : null);
|
|
323
|
+
this.uniforms.clim5.value.set(contrastLimits.length > 5 ? contrastLimits[5][0] : null, contrastLimits.length > 5 ? contrastLimits[5][1] : null);
|
|
324
|
+
this.uniforms.clim6.value.set(contrastLimits.length > 6 ? contrastLimits[6][0] : null, contrastLimits.length > 6 ? contrastLimits[6][1] : null);
|
|
325
|
+
// Set clipping planes
|
|
326
|
+
this.uniforms.xClip.value.set(xSlice[0] * (1.0 / this.maxResolution[0]) * this.boxSize[0], xSlice[1] * (1.0 / this.maxResolution[0]) * this.boxSize[0]);
|
|
327
|
+
this.uniforms.yClip.value.set(ySlice[0] * (1.0 / this.maxResolution[1]) * this.boxSize[1], ySlice[1] * (1.0 / this.maxResolution[1]) * this.boxSize[1]);
|
|
328
|
+
this.uniforms.zClip.value.set(zSlice[0] * (1.0 / this.maxResolution[2]) * this.boxSize[2], zSlice[1] * (1.0 / this.maxResolution[2]) * this.boxSize[2]);
|
|
329
|
+
// Set colors (up to 7 channels)
|
|
330
|
+
this.uniforms.color0.value.set(colors.length > 0 ? colors[0][0] : null, colors.length > 0 ? colors[0][1] : null, colors.length > 0 ? colors[0][2] : null, colors.length > 0 ? colors[0][3] : null);
|
|
331
|
+
this.uniforms.color1.value.set(colors.length > 1 ? colors[1][0] : null, colors.length > 1 ? colors[1][1] : null, colors.length > 1 ? colors[1][2] : null, colors.length > 1 ? colors[1][3] : null);
|
|
332
|
+
this.uniforms.color2.value.set(colors.length > 2 ? colors[2][0] : null, colors.length > 2 ? colors[2][1] : null, colors.length > 2 ? colors[2][2] : null, colors.length > 2 ? colors[2][3] : null);
|
|
333
|
+
this.uniforms.color3.value.set(colors.length > 3 ? colors[3][0] : null, colors.length > 3 ? colors[3][1] : null, colors.length > 3 ? colors[3][2] : null, colors.length > 3 ? colors[3][3] : null);
|
|
334
|
+
this.uniforms.color4.value.set(colors.length > 4 ? colors[4][0] : null, colors.length > 4 ? colors[4][1] : null, colors.length > 4 ? colors[4][2] : null, colors.length > 4 ? colors[4][3] : null);
|
|
335
|
+
this.uniforms.color5.value.set(colors.length > 5 ? colors[5][0] : null, colors.length > 5 ? colors[5][1] : null, colors.length > 5 ? colors[5][2] : null, colors.length > 5 ? colors[5][3] : null);
|
|
336
|
+
this.uniforms.color6.value.set(colors.length > 6 ? colors[6][0] : null, colors.length > 6 ? colors[6][1] : null, colors.length > 6 ? colors[6][2] : null, colors.length > 6 ? colors[6][3] : null);
|
|
337
|
+
for (let i = 0; i < 7; i++) {
|
|
338
|
+
if (typeof this.channelMaxResolutionIndex[i] === 'number') {
|
|
339
|
+
this.uniforms[`res${i}`].value.set(Math.max(1, this.channelMaxResolutionIndex[i]), this.zarrStoreNumResolutions - 1);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Sets the processing render target
|
|
345
|
+
* @param {WebGLMultipleRenderTargets} mrt - Multiple render targets object with 3 attachments
|
|
346
|
+
*/
|
|
347
|
+
/*
|
|
348
|
+
setProcessingTargets(mrt) {
|
|
349
|
+
logWithColor('setting processing targets');
|
|
350
|
+
this.mrt = mrt;
|
|
351
|
+
}
|
|
352
|
+
*/
|
|
353
|
+
setChannelMapping(channelMapping) {
|
|
354
|
+
logWithColor('setting channel mapping');
|
|
355
|
+
log.debug('channelMapping', channelMapping);
|
|
356
|
+
this.uniforms.channelMapping.value = channelMapping;
|
|
357
|
+
}
|
|
358
|
+
// Only called on initialization of the
|
|
359
|
+
// VolumeDataManager and VolumeRenderManager for a particular image.
|
|
360
|
+
setZarrUniforms(zarrStore, PT) {
|
|
361
|
+
logWithColor('setting zarr uniforms');
|
|
362
|
+
log.debug('zarrStore', zarrStore);
|
|
363
|
+
log.debug('PT', PT);
|
|
364
|
+
for (let i = 0; i <= 9; i++) {
|
|
365
|
+
if (PT.anchors && PT.anchors[i]) {
|
|
366
|
+
this.uniforms[`anchor${i}`].value.set(PT.anchors[i][0] || 0, PT.anchors[i][1] || 0, PT.anchors[i][2] || 0);
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
// Set default values if anchor doesn't exist
|
|
370
|
+
log.debug('anchor', i, 'does not exist');
|
|
371
|
+
this.uniforms[`anchor${i}`].value.set(0, 0, 0);
|
|
372
|
+
}
|
|
373
|
+
if (zarrStore.scales && zarrStore.scales[i]) {
|
|
374
|
+
this.uniforms[`scale${i}`].value.set(zarrStore.scales[i][0] || 1, zarrStore.scales[i][1] || 1, zarrStore.scales[i][2] || 1);
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
log.debug('scale', i, 'does not exist');
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
log.debug('zarrStore.brickLayout', zarrStore.brickLayout);
|
|
381
|
+
this.zarrStoreNumResolutions = zarrStore.brickLayout.length;
|
|
382
|
+
for (let i = 0; i < 7; i++) {
|
|
383
|
+
this.uniforms[`res${i}`].value.set(
|
|
384
|
+
// TODO(mark) make this dependent on the per-channel maxResolution slider value.
|
|
385
|
+
1, zarrStore.brickLayout.length - 1);
|
|
386
|
+
}
|
|
387
|
+
this.uniforms.resGlobal.value.set(1, zarrStore.brickLayout.length - 1);
|
|
388
|
+
this.uniforms.voxelExtents.value.set(zarrStore.shapes[0][4], zarrStore.shapes[0][3], zarrStore.shapes[0][2]);
|
|
389
|
+
this.uniforms.maxChannels.value = Math.min(zarrStore.channelCount, 7);
|
|
390
|
+
log.debug('this.channelsVisible', this.channelsVisible);
|
|
391
|
+
log.debug('zarrStore.shapes[0]', zarrStore.shapes[0]);
|
|
392
|
+
log.debug('PT', PT);
|
|
393
|
+
log.debug('uniforms', this.uniforms);
|
|
394
|
+
// this.uniforms.physicalScale.value.set(physicalScale);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
export namespace VolumeShader {
|
|
2
|
+
export namespace uniforms {
|
|
3
|
+
namespace u_size {
|
|
4
|
+
let value: Vector3;
|
|
5
|
+
}
|
|
6
|
+
namespace clim0 {
|
|
7
|
+
let value_1: Vector2;
|
|
8
|
+
export { value_1 as value };
|
|
9
|
+
}
|
|
10
|
+
namespace clim1 {
|
|
11
|
+
let value_2: Vector2;
|
|
12
|
+
export { value_2 as value };
|
|
13
|
+
}
|
|
14
|
+
namespace clim2 {
|
|
15
|
+
let value_3: Vector2;
|
|
16
|
+
export { value_3 as value };
|
|
17
|
+
}
|
|
18
|
+
namespace clim3 {
|
|
19
|
+
let value_4: Vector2;
|
|
20
|
+
export { value_4 as value };
|
|
21
|
+
}
|
|
22
|
+
namespace clim4 {
|
|
23
|
+
let value_5: Vector2;
|
|
24
|
+
export { value_5 as value };
|
|
25
|
+
}
|
|
26
|
+
namespace clim5 {
|
|
27
|
+
let value_6: Vector2;
|
|
28
|
+
export { value_6 as value };
|
|
29
|
+
}
|
|
30
|
+
namespace clim6 {
|
|
31
|
+
let value_7: Vector2;
|
|
32
|
+
export { value_7 as value };
|
|
33
|
+
}
|
|
34
|
+
namespace clim7 {
|
|
35
|
+
let value_8: Vector2;
|
|
36
|
+
export { value_8 as value };
|
|
37
|
+
}
|
|
38
|
+
namespace xClip {
|
|
39
|
+
let value_9: Vector2;
|
|
40
|
+
export { value_9 as value };
|
|
41
|
+
}
|
|
42
|
+
namespace yClip {
|
|
43
|
+
let value_10: Vector2;
|
|
44
|
+
export { value_10 as value };
|
|
45
|
+
}
|
|
46
|
+
namespace zClip {
|
|
47
|
+
let value_11: Vector2;
|
|
48
|
+
export { value_11 as value };
|
|
49
|
+
}
|
|
50
|
+
namespace u_window_size {
|
|
51
|
+
let value_12: Vector2;
|
|
52
|
+
export { value_12 as value };
|
|
53
|
+
}
|
|
54
|
+
namespace u_vol_scale {
|
|
55
|
+
let value_13: Vector3;
|
|
56
|
+
export { value_13 as value };
|
|
57
|
+
}
|
|
58
|
+
namespace u_renderstyle {
|
|
59
|
+
let value_14: number;
|
|
60
|
+
export { value_14 as value };
|
|
61
|
+
}
|
|
62
|
+
namespace brickCacheTex {
|
|
63
|
+
export let type: string;
|
|
64
|
+
let value_15: null;
|
|
65
|
+
export { value_15 as value };
|
|
66
|
+
}
|
|
67
|
+
namespace pageTableTex {
|
|
68
|
+
let type_1: string;
|
|
69
|
+
export { type_1 as type };
|
|
70
|
+
let value_16: null;
|
|
71
|
+
export { value_16 as value };
|
|
72
|
+
}
|
|
73
|
+
namespace color0 {
|
|
74
|
+
let value_17: Vector4;
|
|
75
|
+
export { value_17 as value };
|
|
76
|
+
}
|
|
77
|
+
namespace color1 {
|
|
78
|
+
let value_18: Vector4;
|
|
79
|
+
export { value_18 as value };
|
|
80
|
+
}
|
|
81
|
+
namespace color2 {
|
|
82
|
+
let value_19: Vector4;
|
|
83
|
+
export { value_19 as value };
|
|
84
|
+
}
|
|
85
|
+
namespace color3 {
|
|
86
|
+
let value_20: Vector4;
|
|
87
|
+
export { value_20 as value };
|
|
88
|
+
}
|
|
89
|
+
namespace color4 {
|
|
90
|
+
let value_21: Vector4;
|
|
91
|
+
export { value_21 as value };
|
|
92
|
+
}
|
|
93
|
+
namespace color5 {
|
|
94
|
+
let value_22: Vector4;
|
|
95
|
+
export { value_22 as value };
|
|
96
|
+
}
|
|
97
|
+
namespace color6 {
|
|
98
|
+
let value_23: Vector4;
|
|
99
|
+
export { value_23 as value };
|
|
100
|
+
}
|
|
101
|
+
namespace channelMapping {
|
|
102
|
+
let value_24: number[];
|
|
103
|
+
export { value_24 as value };
|
|
104
|
+
}
|
|
105
|
+
namespace resGlobal {
|
|
106
|
+
let value_25: Vector2;
|
|
107
|
+
export { value_25 as value };
|
|
108
|
+
}
|
|
109
|
+
namespace res0 {
|
|
110
|
+
let value_26: Vector2;
|
|
111
|
+
export { value_26 as value };
|
|
112
|
+
}
|
|
113
|
+
namespace res1 {
|
|
114
|
+
let value_27: Vector2;
|
|
115
|
+
export { value_27 as value };
|
|
116
|
+
}
|
|
117
|
+
namespace res2 {
|
|
118
|
+
let value_28: Vector2;
|
|
119
|
+
export { value_28 as value };
|
|
120
|
+
}
|
|
121
|
+
namespace res3 {
|
|
122
|
+
let value_29: Vector2;
|
|
123
|
+
export { value_29 as value };
|
|
124
|
+
}
|
|
125
|
+
namespace res4 {
|
|
126
|
+
let value_30: Vector2;
|
|
127
|
+
export { value_30 as value };
|
|
128
|
+
}
|
|
129
|
+
namespace res5 {
|
|
130
|
+
let value_31: Vector2;
|
|
131
|
+
export { value_31 as value };
|
|
132
|
+
}
|
|
133
|
+
namespace res6 {
|
|
134
|
+
let value_32: Vector2;
|
|
135
|
+
export { value_32 as value };
|
|
136
|
+
}
|
|
137
|
+
namespace maxChannels {
|
|
138
|
+
let value_33: number;
|
|
139
|
+
export { value_33 as value };
|
|
140
|
+
}
|
|
141
|
+
namespace lodFactor {
|
|
142
|
+
let value_34: number;
|
|
143
|
+
export { value_34 as value };
|
|
144
|
+
}
|
|
145
|
+
namespace near {
|
|
146
|
+
let value_35: number;
|
|
147
|
+
export { value_35 as value };
|
|
148
|
+
}
|
|
149
|
+
namespace far {
|
|
150
|
+
let value_36: number;
|
|
151
|
+
export { value_36 as value };
|
|
152
|
+
}
|
|
153
|
+
namespace opacity {
|
|
154
|
+
let value_37: number;
|
|
155
|
+
export { value_37 as value };
|
|
156
|
+
}
|
|
157
|
+
namespace volumeCount {
|
|
158
|
+
let value_38: number;
|
|
159
|
+
export { value_38 as value };
|
|
160
|
+
}
|
|
161
|
+
namespace boxSize {
|
|
162
|
+
let value_39: Vector3;
|
|
163
|
+
export { value_39 as value };
|
|
164
|
+
}
|
|
165
|
+
namespace renderRes {
|
|
166
|
+
let value_40: number;
|
|
167
|
+
export { value_40 as value };
|
|
168
|
+
}
|
|
169
|
+
namespace voxelExtents {
|
|
170
|
+
let value_41: Vector3;
|
|
171
|
+
export { value_41 as value };
|
|
172
|
+
}
|
|
173
|
+
namespace anchor0 {
|
|
174
|
+
let value_42: Vector3;
|
|
175
|
+
export { value_42 as value };
|
|
176
|
+
}
|
|
177
|
+
namespace anchor1 {
|
|
178
|
+
let value_43: Vector3;
|
|
179
|
+
export { value_43 as value };
|
|
180
|
+
}
|
|
181
|
+
namespace anchor2 {
|
|
182
|
+
let value_44: Vector3;
|
|
183
|
+
export { value_44 as value };
|
|
184
|
+
}
|
|
185
|
+
namespace anchor3 {
|
|
186
|
+
let value_45: Vector3;
|
|
187
|
+
export { value_45 as value };
|
|
188
|
+
}
|
|
189
|
+
namespace anchor4 {
|
|
190
|
+
let value_46: Vector3;
|
|
191
|
+
export { value_46 as value };
|
|
192
|
+
}
|
|
193
|
+
namespace anchor5 {
|
|
194
|
+
let value_47: Vector3;
|
|
195
|
+
export { value_47 as value };
|
|
196
|
+
}
|
|
197
|
+
namespace anchor6 {
|
|
198
|
+
let value_48: Vector3;
|
|
199
|
+
export { value_48 as value };
|
|
200
|
+
}
|
|
201
|
+
namespace anchor7 {
|
|
202
|
+
let value_49: Vector3;
|
|
203
|
+
export { value_49 as value };
|
|
204
|
+
}
|
|
205
|
+
namespace anchor8 {
|
|
206
|
+
let value_50: Vector3;
|
|
207
|
+
export { value_50 as value };
|
|
208
|
+
}
|
|
209
|
+
namespace anchor9 {
|
|
210
|
+
let value_51: Vector3;
|
|
211
|
+
export { value_51 as value };
|
|
212
|
+
}
|
|
213
|
+
namespace scale0 {
|
|
214
|
+
let value_52: Vector3;
|
|
215
|
+
export { value_52 as value };
|
|
216
|
+
}
|
|
217
|
+
namespace scale1 {
|
|
218
|
+
let value_53: Vector3;
|
|
219
|
+
export { value_53 as value };
|
|
220
|
+
}
|
|
221
|
+
namespace scale2 {
|
|
222
|
+
let value_54: Vector3;
|
|
223
|
+
export { value_54 as value };
|
|
224
|
+
}
|
|
225
|
+
namespace scale3 {
|
|
226
|
+
let value_55: Vector3;
|
|
227
|
+
export { value_55 as value };
|
|
228
|
+
}
|
|
229
|
+
namespace scale4 {
|
|
230
|
+
let value_56: Vector3;
|
|
231
|
+
export { value_56 as value };
|
|
232
|
+
}
|
|
233
|
+
namespace scale5 {
|
|
234
|
+
let value_57: Vector3;
|
|
235
|
+
export { value_57 as value };
|
|
236
|
+
}
|
|
237
|
+
namespace scale6 {
|
|
238
|
+
let value_58: Vector3;
|
|
239
|
+
export { value_58 as value };
|
|
240
|
+
}
|
|
241
|
+
namespace scale7 {
|
|
242
|
+
let value_59: Vector3;
|
|
243
|
+
export { value_59 as value };
|
|
244
|
+
}
|
|
245
|
+
namespace scale8 {
|
|
246
|
+
let value_60: Vector3;
|
|
247
|
+
export { value_60 as value };
|
|
248
|
+
}
|
|
249
|
+
namespace scale9 {
|
|
250
|
+
let value_61: Vector3;
|
|
251
|
+
export { value_61 as value };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
export { volumeVertexShader as vertexShader };
|
|
255
|
+
export { volumeFragmentShader as fragmentShader };
|
|
256
|
+
}
|
|
257
|
+
import { Vector3 } from 'three';
|
|
258
|
+
import { Vector2 } from 'three';
|
|
259
|
+
import { Vector4 } from 'three';
|
|
260
|
+
import { volumeVertexShader } from './shaders/VolumeVertexShader.js';
|
|
261
|
+
import { volumeFragmentShader } from './shaders/VolumeFragmentShader.js';
|
|
262
|
+
//# sourceMappingURL=VolumeShader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VolumeShader.d.ts","sourceRoot":"","sources":["../src/VolumeShader.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAA0C,OAAO;wBAAP,OAAO;wBAAP,OAAO;mCACd,iCAAiC;qCAC/B,mCAAmC"}
|