@kitware/vtk.js 22.6.1 → 23.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/Common/DataModel/ITKHelper.js +16 -20
- package/Common/DataModel/ImageData.d.ts +35 -35
- package/Filters/General/ImageSliceFilter.d.ts +1 -1
- package/Filters/General/ImageStreamline.d.ts +135 -0
- package/IO/Core/DataAccessHelper/HtmlDataAccessHelper.d.ts +9 -0
- package/IO/Core/DataAccessHelper/HttpDataAccessHelper.d.ts +9 -0
- package/IO/Core/DataAccessHelper/JSZipDataAccessHelper.d.ts +13 -0
- package/IO/Core/DataAccessHelper/LiteHttpDataAccessHelper.d.ts +9 -0
- package/IO/Core/DataAccessHelper.d.ts +32 -0
- package/IO/Core/HttpDataSetReader.d.ts +226 -0
- package/IO/Geometry/DracoReader.d.ts +12 -8
- package/IO/Geometry/PLYReader.d.ts +12 -8
- package/IO/Geometry/STLReader.d.ts +13 -8
- package/IO/Misc/ElevationReader.d.ts +10 -5
- package/IO/Misc/JSONNucleoReader.d.ts +12 -8
- package/IO/Misc/JSONReader.d.ts +3 -3
- package/IO/Misc/MTLReader.d.ts +9 -5
- package/IO/Misc/OBJReader.d.ts +9 -5
- package/IO/Misc/PDBReader.d.ts +9 -5
- package/IO/XML/XMLReader.d.ts +19 -15
- package/Interaction/Widgets/OrientationMarkerWidget.d.ts +12 -0
- package/Interaction/Widgets/OrientationMarkerWidget.js +62 -37
- package/Rendering/Core/Actor.d.ts +17 -14
- package/Rendering/Core/ImageProperty.d.ts +9 -0
- package/Rendering/Core/ImageProperty.js +3 -2
- package/Rendering/Core/Renderer.d.ts +5 -5
- package/Rendering/OpenGL/ImageMapper.js +1 -1
- package/Rendering/OpenGL/VolumeMapper.js +16 -1
- package/Rendering/OpenGL/glsl/vtkVolumeFS.glsl.js +1 -1
- package/Rendering/WebGPU/ImageMapper.js +1 -1
- package/Widgets/Core/AbstractWidgetFactory.js +5 -3
- package/index.d.ts +7 -0
- package/package.json +1 -1
package/IO/XML/XMLReader.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { vtkAlgorithm, vtkObject } from '@kitware/vtk.js/interfaces';
|
|
2
|
+
import HtmlDataAccessHelper from '@kitware/vtk.js/IO/Core/DataAccessHelper/HtmlDataAccessHelper';
|
|
3
|
+
import HttpDataAccessHelper from '@kitware/vtk.js/IO/Core/DataAccessHelper/HttpDataAccessHelper';
|
|
4
|
+
import JSZipDataAccessHelper from '@kitware/vtk.js/IO/Core/DataAccessHelper/JSZipDataAccessHelper';
|
|
5
|
+
import LiteHttpDataAccessHelper from '@kitware/vtk.js/IO/Core/DataAccessHelper/LiteHttpDataAccessHelper';
|
|
2
6
|
|
|
3
7
|
|
|
4
8
|
interface IXMLReaderOptions {
|
|
@@ -36,7 +40,7 @@ export interface vtkXMLReader extends vtkXMLReaderBase {
|
|
|
36
40
|
/**
|
|
37
41
|
*
|
|
38
42
|
*/
|
|
39
|
-
getDataAccessHelper():
|
|
43
|
+
getDataAccessHelper(): HtmlDataAccessHelper | HttpDataAccessHelper | JSZipDataAccessHelper | LiteHttpDataAccessHelper;
|
|
40
44
|
|
|
41
45
|
/**
|
|
42
46
|
* Get the url of the object to load.
|
|
@@ -74,17 +78,17 @@ export interface vtkXMLReader extends vtkXMLReaderBase {
|
|
|
74
78
|
requestData(inData: any, outData: any): void;
|
|
75
79
|
|
|
76
80
|
/**
|
|
77
|
-
*
|
|
78
|
-
* @param
|
|
79
|
-
* @param {IXMLReaderOptions} [option] The XML reader options.
|
|
81
|
+
*
|
|
82
|
+
* @param dataAccessHelper
|
|
80
83
|
*/
|
|
81
|
-
|
|
84
|
+
setDataAccessHelper(dataAccessHelper: HtmlDataAccessHelper | HttpDataAccessHelper | JSZipDataAccessHelper | LiteHttpDataAccessHelper): boolean;
|
|
82
85
|
|
|
83
86
|
/**
|
|
84
|
-
*
|
|
85
|
-
* @param
|
|
87
|
+
* Set the url of the object to load.
|
|
88
|
+
* @param {String} url the url of the object to load.
|
|
89
|
+
* @param {IXMLReaderOptions} [option] The XML reader options.
|
|
86
90
|
*/
|
|
87
|
-
|
|
91
|
+
setUrl(url: string, option?: IXMLReaderOptions): Promise<any>;
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
/**
|
|
@@ -98,34 +102,34 @@ export function extend(publicAPI: object, model: object, initialValues?: IXMLRea
|
|
|
98
102
|
|
|
99
103
|
/**
|
|
100
104
|
* @param {Number} size
|
|
101
|
-
* @param dataArrayElem
|
|
105
|
+
* @param {HTMLElement} dataArrayElem
|
|
102
106
|
* @param {String} compressor
|
|
103
107
|
* @param {String} byteOrder
|
|
104
108
|
* @param {String} headerType
|
|
105
109
|
* @param {ArrayBuffer} binaryBuffer
|
|
106
110
|
*/
|
|
107
|
-
export function processDataArray(size: number, dataArrayElem:
|
|
111
|
+
export function processDataArray(size: number, dataArrayElem: HTMLElement, compressor: string, byteOrder: string, headerType: string, binaryBuffer: ArrayBuffer): IRet;
|
|
108
112
|
|
|
109
113
|
/**
|
|
110
114
|
* @param {Number} size
|
|
111
|
-
* @param containerElem
|
|
115
|
+
* @param {HTMLElement} containerElem
|
|
112
116
|
* @param {String} compressor
|
|
113
117
|
* @param {String} byteOrder
|
|
114
118
|
* @param {String} headerType
|
|
115
119
|
* @param {ArrayBuffer} binaryBuffer
|
|
116
120
|
*/
|
|
117
|
-
export function processCells(size: number, containerElem:
|
|
121
|
+
export function processCells(size: number, containerElem: HTMLElement, compressor: string, byteOrder: string, headerType: string, binaryBuffer: ArrayBuffer): Uint32Array;
|
|
118
122
|
|
|
119
123
|
/**
|
|
120
124
|
* @param {Number} size
|
|
121
|
-
* @param fieldElem
|
|
122
|
-
* @param fieldContainer
|
|
125
|
+
* @param {HTMLElement} fieldElem
|
|
126
|
+
* @param {HTMLElement} fieldContainer
|
|
123
127
|
* @param {String} compressor
|
|
124
128
|
* @param {String} byteOrder
|
|
125
129
|
* @param {String} headerType
|
|
126
130
|
* @param {ArrayBuffer} binaryBuffer
|
|
127
131
|
*/
|
|
128
|
-
export function processFieldData(size: number, fieldElem:
|
|
132
|
+
export function processFieldData(size: number, fieldElem: HTMLElement, fieldContainer: HTMLElement, compressor: string, byteOrder: string, headerType: string, binaryBuffer: ArrayBuffer): void;
|
|
129
133
|
|
|
130
134
|
|
|
131
135
|
/**
|
|
@@ -17,6 +17,7 @@ export enum Corners {
|
|
|
17
17
|
export interface IOrientationMarkerWidgetInitialValues {
|
|
18
18
|
actor?: vtkAnnotatedCubeActor | vtkAxesActor,
|
|
19
19
|
interactor?: vtkRenderWindowInteractor,
|
|
20
|
+
parentRenderer?: vtkRenderer,
|
|
20
21
|
viewportCorner?: Corners,
|
|
21
22
|
viewportSize?: number,
|
|
22
23
|
minPixelSize?: number,
|
|
@@ -44,6 +45,11 @@ export interface vtkOrientationMarkerWidget extends vtkObject {
|
|
|
44
45
|
*/
|
|
45
46
|
getActor(): vtkAnnotatedCubeActor | vtkAxesActor;
|
|
46
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Gets the parent renderer, if any.
|
|
50
|
+
*/
|
|
51
|
+
getParentRenderer(): vtkRenderer | null;
|
|
52
|
+
|
|
47
53
|
/**
|
|
48
54
|
* Get wheter the orientation marker is enabled.
|
|
49
55
|
*/
|
|
@@ -87,6 +93,12 @@ export interface vtkOrientationMarkerWidget extends vtkObject {
|
|
|
87
93
|
*/
|
|
88
94
|
setActor(actor: vtkAnnotatedCubeActor | vtkAxesActor): void;
|
|
89
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Sets the parent renderer
|
|
98
|
+
* @param ren The parent renderer
|
|
99
|
+
*/
|
|
100
|
+
setParentRenderer(ren: vtkRenderer): boolean;
|
|
101
|
+
|
|
90
102
|
/**
|
|
91
103
|
* Set the widget enabled status, i.e. to show the widget or not.
|
|
92
104
|
* @param {Boolean} enabled
|
|
@@ -23,38 +23,49 @@ function vtkOrientationMarkerWidget(publicAPI, model) {
|
|
|
23
23
|
var previousCameraInput = [];
|
|
24
24
|
var selfRenderer = vtkRenderer.newInstance();
|
|
25
25
|
var resizeObserver = new ResizeObserver(function (entries) {
|
|
26
|
-
|
|
27
|
-
publicAPI.updateViewport();
|
|
28
|
-
}
|
|
26
|
+
publicAPI.updateViewport();
|
|
29
27
|
});
|
|
30
|
-
var
|
|
28
|
+
var onAnimationSub = null;
|
|
29
|
+
var onEndAnimationSub = null;
|
|
31
30
|
var selfSubscription = null;
|
|
32
31
|
|
|
33
32
|
publicAPI.computeViewport = function () {
|
|
34
|
-
var
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
var parentRen = model.parentRenderer || model.interactor.getCurrentRenderer();
|
|
34
|
+
|
|
35
|
+
var _parentRen$getViewpor = parentRen.getViewport(),
|
|
36
|
+
_parentRen$getViewpor2 = _slicedToArray(_parentRen$getViewpor, 4),
|
|
37
|
+
xMin = _parentRen$getViewpor2[0],
|
|
38
|
+
yMin = _parentRen$getViewpor2[1],
|
|
39
|
+
xMax = _parentRen$getViewpor2[2],
|
|
40
|
+
yMax = _parentRen$getViewpor2[3];
|
|
41
|
+
|
|
42
|
+
var view = model.interactor.getView();
|
|
43
|
+
var canvasSize = view.getSize();
|
|
44
|
+
|
|
45
|
+
var _view$getViewportSize = view.getViewportSize(parentRen),
|
|
46
|
+
_view$getViewportSize2 = _slicedToArray(_view$getViewportSize, 2),
|
|
47
|
+
viewXSize = _view$getViewportSize2[0],
|
|
48
|
+
viewYSize = _view$getViewportSize2[1];
|
|
38
49
|
|
|
39
50
|
var minViewSize = Math.min(viewXSize, viewYSize);
|
|
40
51
|
var pixelSize = model.viewportSize * minViewSize; // clamp pixel size
|
|
41
52
|
|
|
42
53
|
pixelSize = Math.max(Math.min(model.minPixelSize, minViewSize), Math.min(model.maxPixelSize, pixelSize));
|
|
43
|
-
var xFrac = pixelSize /
|
|
44
|
-
var yFrac = pixelSize /
|
|
54
|
+
var xFrac = pixelSize / canvasSize[0];
|
|
55
|
+
var yFrac = pixelSize / canvasSize[1]; // [left bottom right top]
|
|
45
56
|
|
|
46
57
|
switch (model.viewportCorner) {
|
|
47
58
|
case Corners.TOP_LEFT:
|
|
48
|
-
return [
|
|
59
|
+
return [xMin, yMax - yFrac, xMin + xFrac, yMax];
|
|
49
60
|
|
|
50
61
|
case Corners.TOP_RIGHT:
|
|
51
|
-
return [
|
|
62
|
+
return [xMax - xFrac, yMax - yFrac, xMax, yMax];
|
|
52
63
|
|
|
53
64
|
case Corners.BOTTOM_LEFT:
|
|
54
|
-
return [
|
|
65
|
+
return [xMin, yMin, xMin + xFrac, yMin + yFrac];
|
|
55
66
|
|
|
56
67
|
case Corners.BOTTOM_RIGHT:
|
|
57
|
-
return [
|
|
68
|
+
return [xMax - xFrac, yMin, xMax, yMin + yFrac];
|
|
58
69
|
|
|
59
70
|
default:
|
|
60
71
|
vtkErrorMacro('Invalid widget corner');
|
|
@@ -63,12 +74,15 @@ function vtkOrientationMarkerWidget(publicAPI, model) {
|
|
|
63
74
|
};
|
|
64
75
|
|
|
65
76
|
publicAPI.updateViewport = function () {
|
|
66
|
-
|
|
67
|
-
|
|
77
|
+
if (model.enabled) {
|
|
78
|
+
selfRenderer.setViewport.apply(selfRenderer, _toConsumableArray(publicAPI.computeViewport()));
|
|
79
|
+
model.interactor.render();
|
|
80
|
+
}
|
|
68
81
|
};
|
|
69
82
|
|
|
70
83
|
publicAPI.updateMarkerOrientation = function () {
|
|
71
|
-
var
|
|
84
|
+
var ren = model.parentRenderer || model.interactor.getCurrentRenderer();
|
|
85
|
+
var currentCamera = ren.getActiveCamera();
|
|
72
86
|
|
|
73
87
|
if (!currentCamera) {
|
|
74
88
|
return;
|
|
@@ -116,7 +130,8 @@ function vtkOrientationMarkerWidget(publicAPI, model) {
|
|
|
116
130
|
return;
|
|
117
131
|
}
|
|
118
132
|
|
|
119
|
-
var
|
|
133
|
+
var ren = model.parentRenderer || model.interactor.getCurrentRenderer();
|
|
134
|
+
var renderWindow = ren.getRenderWindow();
|
|
120
135
|
renderWindow.addRenderer(selfRenderer);
|
|
121
136
|
|
|
122
137
|
if (renderWindow.getNumberOfLayers() < 2) {
|
|
@@ -128,10 +143,8 @@ function vtkOrientationMarkerWidget(publicAPI, model) {
|
|
|
128
143
|
selfRenderer.setInteractive(false);
|
|
129
144
|
selfRenderer.addViewProp(model.actor);
|
|
130
145
|
model.actor.setVisibility(true);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
interactorUnsubscribe = _model$interactor$onA.unsubscribe;
|
|
146
|
+
onAnimationSub = model.interactor.onAnimation(publicAPI.updateMarkerOrientation);
|
|
147
|
+
onEndAnimationSub = model.interactor.onEndAnimation(publicAPI.updateMarkerOrientation);
|
|
135
148
|
resizeObserver.observe(model.interactor.getView().getCanvas());
|
|
136
149
|
publicAPI.updateViewport();
|
|
137
150
|
publicAPI.updateMarkerOrientation();
|
|
@@ -143,8 +156,10 @@ function vtkOrientationMarkerWidget(publicAPI, model) {
|
|
|
143
156
|
|
|
144
157
|
model.enabled = false;
|
|
145
158
|
resizeObserver.disconnect();
|
|
146
|
-
|
|
147
|
-
|
|
159
|
+
onAnimationSub.unsubscribe();
|
|
160
|
+
onAnimationSub = null;
|
|
161
|
+
onEndAnimationSub.unsubscribe();
|
|
162
|
+
onEndAnimationSub = null;
|
|
148
163
|
model.actor.setVisibility(false);
|
|
149
164
|
selfRenderer.removeViewProp(model.actor);
|
|
150
165
|
|
|
@@ -168,10 +183,7 @@ function vtkOrientationMarkerWidget(publicAPI, model) {
|
|
|
168
183
|
}
|
|
169
184
|
|
|
170
185
|
model.viewportCorner = corner;
|
|
171
|
-
|
|
172
|
-
if (model.enabled) {
|
|
173
|
-
publicAPI.updateViewport();
|
|
174
|
-
}
|
|
186
|
+
publicAPI.updateViewport();
|
|
175
187
|
};
|
|
176
188
|
/**
|
|
177
189
|
* Sets the viewport size.
|
|
@@ -186,10 +198,7 @@ function vtkOrientationMarkerWidget(publicAPI, model) {
|
|
|
186
198
|
}
|
|
187
199
|
|
|
188
200
|
model.viewportSize = viewportSize;
|
|
189
|
-
|
|
190
|
-
if (model.enabled) {
|
|
191
|
-
publicAPI.updateViewport();
|
|
192
|
-
}
|
|
201
|
+
publicAPI.updateViewport();
|
|
193
202
|
};
|
|
194
203
|
|
|
195
204
|
publicAPI.setActor = function (actor) {
|
|
@@ -199,6 +208,16 @@ function vtkOrientationMarkerWidget(publicAPI, model) {
|
|
|
199
208
|
publicAPI.setEnabled(previousState);
|
|
200
209
|
};
|
|
201
210
|
|
|
211
|
+
publicAPI.setParentRenderer = function (ren) {
|
|
212
|
+
var changed = superClass.setParentRenderer(ren);
|
|
213
|
+
|
|
214
|
+
if (changed) {
|
|
215
|
+
publicAPI.updateViewport();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return changed;
|
|
219
|
+
};
|
|
220
|
+
|
|
202
221
|
publicAPI.getRenderer = function () {
|
|
203
222
|
return selfRenderer;
|
|
204
223
|
};
|
|
@@ -211,9 +230,14 @@ function vtkOrientationMarkerWidget(publicAPI, model) {
|
|
|
211
230
|
selfSubscription = null;
|
|
212
231
|
}
|
|
213
232
|
|
|
214
|
-
if (
|
|
215
|
-
|
|
216
|
-
|
|
233
|
+
if (onAnimationSub) {
|
|
234
|
+
onAnimationSub.unsubscribe();
|
|
235
|
+
onAnimationSub = null;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (onEndAnimationSub) {
|
|
239
|
+
onEndAnimationSub.unsubscribe();
|
|
240
|
+
onEndAnimationSub = null;
|
|
217
241
|
}
|
|
218
242
|
|
|
219
243
|
resizeObserver.disconnect();
|
|
@@ -233,7 +257,8 @@ var DEFAULT_VALUES = {
|
|
|
233
257
|
viewportCorner: Constants.Corners.BOTTOM_LEFT,
|
|
234
258
|
viewportSize: 0.2,
|
|
235
259
|
minPixelSize: 50,
|
|
236
|
-
maxPixelSize: 200
|
|
260
|
+
maxPixelSize: 200,
|
|
261
|
+
parentRenderer: null
|
|
237
262
|
}; // ----------------------------------------------------------------------------
|
|
238
263
|
|
|
239
264
|
function extend(publicAPI, model) {
|
|
@@ -244,7 +269,7 @@ function extend(publicAPI, model) {
|
|
|
244
269
|
macro.get(publicAPI, model, ['enabled', 'viewportCorner', 'viewportSize']); // NOTE: setting these while the widget is enabled will
|
|
245
270
|
// not update the widget.
|
|
246
271
|
|
|
247
|
-
macro.setGet(publicAPI, model, ['interactor', 'minPixelSize', 'maxPixelSize']);
|
|
272
|
+
macro.setGet(publicAPI, model, ['interactor', 'minPixelSize', 'maxPixelSize', 'parentRenderer']);
|
|
248
273
|
macro.get(publicAPI, model, ['actor']); // Object methods
|
|
249
274
|
|
|
250
275
|
vtkOrientationMarkerWidget(publicAPI, model);
|
|
@@ -31,7 +31,8 @@ export interface vtkActor extends vtkProp3D {
|
|
|
31
31
|
getActors(): vtkActor[];
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* Get the property object that controls this actors backface surface
|
|
35
|
+
* properties.
|
|
35
36
|
* @return {vtkProperty} the backface property.
|
|
36
37
|
*/
|
|
37
38
|
getBackfaceProperty(): vtkProperty;
|
|
@@ -59,7 +60,7 @@ export interface vtkActor extends vtkProp3D {
|
|
|
59
60
|
getIsOpaque(): boolean;
|
|
60
61
|
|
|
61
62
|
/**
|
|
62
|
-
*
|
|
63
|
+
* Get the Mapper that this actor is getting its data from.
|
|
63
64
|
*/
|
|
64
65
|
getMapper(): null | vtkMapper;
|
|
65
66
|
|
|
@@ -85,32 +86,34 @@ export interface vtkActor extends vtkProp3D {
|
|
|
85
86
|
makeProperty(): vtkProperty;
|
|
86
87
|
|
|
87
88
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
89
|
+
* Set the property object that controls this actors backface surface
|
|
90
|
+
* properties.
|
|
91
|
+
* @param {vtkProperty} backfaceProperty The backfaceProperty instance.
|
|
90
92
|
*/
|
|
91
93
|
setBackfaceProperty(backfaceProperty: vtkProperty): boolean;
|
|
92
94
|
|
|
93
95
|
/**
|
|
94
|
-
*
|
|
95
|
-
* @param forceOpaque
|
|
96
|
+
* Force the actor to be treated as opaque or translucent.
|
|
97
|
+
* @param {Boolean} forceOpaque
|
|
96
98
|
*/
|
|
97
|
-
setForceOpaque(forceOpaque:
|
|
99
|
+
setForceOpaque(forceOpaque: boolean): boolean;
|
|
98
100
|
|
|
99
101
|
/**
|
|
100
|
-
*
|
|
101
|
-
* @param forceTranslucent
|
|
102
|
+
* Force the actor to be treated as opaque or translucent.
|
|
103
|
+
* @param {Boolean} forceTranslucent
|
|
102
104
|
*/
|
|
103
105
|
setForceTranslucent(forceTranslucent: boolean): boolean;
|
|
104
106
|
|
|
105
107
|
/**
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
+
* This is the method that is used to connect an actor to the end of a
|
|
109
|
+
* visualization pipeline, i.e. the mapper.
|
|
110
|
+
* @param {vtkMapper} mapper The vtkMapper instance.
|
|
108
111
|
*/
|
|
109
|
-
setMapper(mapper:
|
|
112
|
+
setMapper(mapper: vtkMapper): boolean;
|
|
110
113
|
|
|
111
114
|
/**
|
|
112
|
-
*
|
|
113
|
-
* @param property
|
|
115
|
+
* Set the property object that controls this actors surface properties.
|
|
116
|
+
* @param {vtkProperty} property The vtkProperty instance.
|
|
114
117
|
*/
|
|
115
118
|
setProperty(property: vtkProperty): boolean;
|
|
116
119
|
}
|
|
@@ -20,6 +20,7 @@ export interface IImageMapperInitialValues {
|
|
|
20
20
|
diffuse?: number;
|
|
21
21
|
opacity?: number;
|
|
22
22
|
componentData?: IComponentData[];
|
|
23
|
+
useLookupTableScalarRange?: boolean;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export interface vtkImageProperty extends vtkObject {
|
|
@@ -173,6 +174,14 @@ export interface vtkImageProperty extends vtkObject {
|
|
|
173
174
|
* @param func
|
|
174
175
|
*/
|
|
175
176
|
setScalarOpacity(index: any, func: any): boolean;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Use the range that is set on the lookup table, instead of setting the range from the
|
|
180
|
+
* ColorWindow/ColorLevel settings
|
|
181
|
+
* @default false
|
|
182
|
+
* @param {Boolean} useLookupTableScalarRange
|
|
183
|
+
*/
|
|
184
|
+
setUseLookupTableScalarRange(useLookupTableScalarRange: boolean): boolean;
|
|
176
185
|
}
|
|
177
186
|
|
|
178
187
|
/**
|
|
@@ -154,7 +154,8 @@ var DEFAULT_VALUES = {
|
|
|
154
154
|
colorLevel: 127.5,
|
|
155
155
|
ambient: 1.0,
|
|
156
156
|
diffuse: 0.0,
|
|
157
|
-
opacity: 1.0
|
|
157
|
+
opacity: 1.0,
|
|
158
|
+
useLookupTableScalarRange: false
|
|
158
159
|
}; // ----------------------------------------------------------------------------
|
|
159
160
|
|
|
160
161
|
function extend(publicAPI, model) {
|
|
@@ -175,7 +176,7 @@ function extend(publicAPI, model) {
|
|
|
175
176
|
}
|
|
176
177
|
}
|
|
177
178
|
|
|
178
|
-
macro.setGet(publicAPI, model, ['independentComponents', 'interpolationType', 'colorWindow', 'colorLevel', 'ambient', 'diffuse', 'opacity']); // Object methods
|
|
179
|
+
macro.setGet(publicAPI, model, ['independentComponents', 'interpolationType', 'colorWindow', 'colorLevel', 'ambient', 'diffuse', 'opacity', 'useLookupTableScalarRange']); // Object methods
|
|
179
180
|
|
|
180
181
|
vtkImageProperty(publicAPI, model);
|
|
181
182
|
} // ----------------------------------------------------------------------------
|
|
@@ -47,14 +47,14 @@ export interface vtkRenderer extends vtkViewport {
|
|
|
47
47
|
isActiveCameraCreated(): boolean;
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
*
|
|
51
|
-
* @param actor
|
|
50
|
+
* Add different types of props to the renderer.
|
|
51
|
+
* @param {vtkActor} actor The vtkActor instance.
|
|
52
52
|
*/
|
|
53
53
|
addActor(actor: vtkActor): boolean;
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Add a light to the list of lights.
|
|
57
|
-
* @param light The vtkLight instance.
|
|
57
|
+
* @param {vtkLight} light The vtkLight instance.
|
|
58
58
|
*/
|
|
59
59
|
addLight(light: vtkLight): void;
|
|
60
60
|
|
|
@@ -75,9 +75,9 @@ export interface vtkRenderer extends vtkViewport {
|
|
|
75
75
|
createLight(): vtkLight;
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
|
-
*
|
|
78
|
+
* Compute the bounding box of all the visible props Used in ResetCamera() and ResetCameraClippingRange()
|
|
79
79
|
*/
|
|
80
|
-
computeVisiblePropBounds():
|
|
80
|
+
computeVisiblePropBounds(): Bounds;
|
|
81
81
|
|
|
82
82
|
/**
|
|
83
83
|
* Get the active camera
|
|
@@ -320,7 +320,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
320
320
|
var target = iComps ? _i : 0;
|
|
321
321
|
var cfun = actor.getProperty().getRGBTransferFunction(target);
|
|
322
322
|
|
|
323
|
-
if (cfun) {
|
|
323
|
+
if (cfun && actor.getProperty().getUseLookupTableScalarRange()) {
|
|
324
324
|
var cRange = cfun.getRange();
|
|
325
325
|
cw = cRange[1] - cRange[0];
|
|
326
326
|
cl = 0.5 * (cRange[1] + cRange[0]);
|
|
@@ -520,6 +520,9 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
520
520
|
var size = publicAPI.getRenderTargetSize();
|
|
521
521
|
program.setUniformf('vpWidth', size[0]);
|
|
522
522
|
program.setUniformf('vpHeight', size[1]);
|
|
523
|
+
var offset = publicAPI.getRenderTargetOffset();
|
|
524
|
+
program.setUniformf('vpOffsetX', offset[0] / size[0]);
|
|
525
|
+
program.setUniformf('vpOffsetY', offset[1] / size[1]);
|
|
523
526
|
}
|
|
524
527
|
}
|
|
525
528
|
|
|
@@ -688,7 +691,19 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
688
691
|
return [model._smallViewportWidth, model._smallViewportHeight];
|
|
689
692
|
}
|
|
690
693
|
|
|
691
|
-
|
|
694
|
+
var _model$openGLRenderer = model.openGLRenderer.getTiledSizeAndOrigin(),
|
|
695
|
+
usize = _model$openGLRenderer.usize,
|
|
696
|
+
vsize = _model$openGLRenderer.vsize;
|
|
697
|
+
|
|
698
|
+
return [usize, vsize];
|
|
699
|
+
};
|
|
700
|
+
|
|
701
|
+
publicAPI.getRenderTargetOffset = function () {
|
|
702
|
+
var _model$openGLRenderer2 = model.openGLRenderer.getTiledSizeAndOrigin(),
|
|
703
|
+
lowerLeftU = _model$openGLRenderer2.lowerLeftU,
|
|
704
|
+
lowerLeftV = _model$openGLRenderer2.lowerLeftV;
|
|
705
|
+
|
|
706
|
+
return [lowerLeftU, lowerLeftV];
|
|
692
707
|
};
|
|
693
708
|
|
|
694
709
|
publicAPI.renderPieceStart = function (ren, actor) {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var vtkVolumeFS = "//VTK::System::Dec\n\n/*=========================================================================\n\n Program: Visualization Toolkit\n Module: vtkVolumeFS.glsl\n\n Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n All rights reserved.\n See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n\n This software is distributed WITHOUT ANY WARRANTY; without even\n the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n PURPOSE. See the above copyright notice for more information.\n\n=========================================================================*/\n// Template for the volume mappers fragment shader\n\n// the output of this shader\n//VTK::Output::Dec\n\nvarying vec3 vertexVCVSOutput;\n\n// first declare the settings from the mapper\n// that impact the code paths in here\n\n// always set vtkNumComponents 1,2,3,4\n//VTK::NumComponents\n\n// possibly define vtkTrilinearOn\n//VTK::TrilinearOn\n\n// possibly define vtkIndependentComponents\n//VTK::IndependentComponentsOn\n\n// possibly define any \"proportional\" components\n//VTK::vtkProportionalComponents\n\n// Define the blend mode to use\n#define vtkBlendMode //VTK::BlendMode\n\n// Possibly define vtkImageLabelOutlineOn\n//VTK::ImageLabelOutlineOn\n\n#ifdef vtkImageLabelOutlineOn\nuniform int outlineThickness;\nuniform float vpWidth;\nuniform float vpHeight;\nuniform mat4 PCWCMatrix;\nuniform mat4 vWCtoIDX;\n#endif\n\n// define vtkLightComplexity\n//VTK::LightComplexity\n#if vtkLightComplexity > 0\nuniform float vSpecularPower;\nuniform float vAmbient;\nuniform float vDiffuse;\nuniform float vSpecular;\n//VTK::Light::Dec\n#endif\n\n// possibly define vtkGradientOpacityOn\n//VTK::GradientOpacityOn\n#ifdef vtkGradientOpacityOn\nuniform float goscale0;\nuniform float goshift0;\nuniform float gomin0;\nuniform float gomax0;\n#if defined(vtkIndependentComponentsOn) && (vtkNumComponents > 1)\nuniform float goscale1;\nuniform float goshift1;\nuniform float gomin1;\nuniform float gomax1;\n#if vtkNumComponents >= 3\nuniform float goscale2;\nuniform float goshift2;\nuniform float gomin2;\nuniform float gomax2;\n#endif\n#if vtkNumComponents >= 4\nuniform float goscale3;\nuniform float goshift3;\nuniform float gomin3;\nuniform float gomax3;\n#endif\n#endif\n#endif\n\n// if you want to see the raw tiled\n// data in webgl1 uncomment the following line\n// #define debugtile\n\n// camera values\nuniform float camThick;\nuniform float camNear;\nuniform float camFar;\nuniform int cameraParallel;\n\n// values describing the volume geometry\nuniform vec3 vOriginVC;\nuniform vec3 vSpacing;\nuniform ivec3 volumeDimensions; // 3d texture dimensions\nuniform vec3 vPlaneNormal0;\nuniform float vPlaneDistance0;\nuniform vec3 vPlaneNormal1;\nuniform float vPlaneDistance1;\nuniform vec3 vPlaneNormal2;\nuniform float vPlaneDistance2;\nuniform vec3 vPlaneNormal3;\nuniform float vPlaneDistance3;\nuniform vec3 vPlaneNormal4;\nuniform float vPlaneDistance4;\nuniform vec3 vPlaneNormal5;\nuniform float vPlaneDistance5;\n\n//VTK::ClipPlane::Dec\n\n// opacity and color textures\nuniform sampler2D otexture;\nuniform float oshift0;\nuniform float oscale0;\nuniform sampler2D ctexture;\nuniform float cshift0;\nuniform float cscale0;\n\n// jitter texture\nuniform sampler2D jtexture;\n\n// some 3D texture values\nuniform float sampleDistance;\nuniform vec3 vVCToIJK;\n\n// the heights defined below are the locations\n// for the up to four components of the tfuns\n// the tfuns have a height of 2XnumComps pixels so the\n// values are computed to hit the middle of the two rows\n// for that component\n#ifdef vtkIndependentComponentsOn\n#if vtkNumComponents == 2\nuniform float mix0;\nuniform float mix1;\n#define height0 0.25\n#define height1 0.75\n#endif\n#if vtkNumComponents == 3\nuniform float mix0;\nuniform float mix1;\nuniform float mix2;\n#define height0 0.17\n#define height1 0.5\n#define height2 0.83\n#endif\n#if vtkNumComponents == 4\nuniform float mix0;\nuniform float mix1;\nuniform float mix2;\nuniform float mix3;\n#define height0 0.125\n#define height1 0.375\n#define height2 0.625\n#define height3 0.875\n#endif\n#endif\n\n#if vtkNumComponents >= 2\nuniform float oshift1;\nuniform float oscale1;\nuniform float cshift1;\nuniform float cscale1;\n#endif\n#if vtkNumComponents >= 3\nuniform float oshift2;\nuniform float oscale2;\nuniform float cshift2;\nuniform float cscale2;\n#endif\n#if vtkNumComponents >= 4\nuniform float oshift3;\nuniform float oscale3;\nuniform float cshift3;\nuniform float cscale3;\n#endif\n\nuniform vec4 ipScalarRangeMin;\nuniform vec4 ipScalarRangeMax;\n\n// declaration for intermixed geometry\n//VTK::ZBuffer::Dec\n\n// Lighting values\n//VTK::Light::Dec\n\n//=======================================================================\n// Webgl2 specific version of functions\n#if __VERSION__ == 300\n\nuniform highp sampler3D texture1;\n\nvec4 getTextureValue(vec3 pos)\n{\n vec4 tmp = texture(texture1, pos);\n#if vtkNumComponents == 1\n tmp.a = tmp.r;\n#endif\n#if vtkNumComponents == 2\n tmp.a = tmp.g;\n#endif\n#if vtkNumComponents == 3\n tmp.a = length(tmp.rgb);\n#endif\n return tmp;\n}\n\n//=======================================================================\n// WebGL1 specific version of functions\n#else\n\nuniform sampler2D texture1;\n\nuniform float texWidth;\nuniform float texHeight;\nuniform int xreps;\nuniform int xstride;\nuniform int ystride;\n\n// if computing trilinear values from multiple z slices\n#ifdef vtkTrilinearOn\nvec4 getTextureValue(vec3 ijk)\n{\n float zoff = 1.0/float(volumeDimensions.z);\n vec4 val1 = getOneTextureValue(ijk);\n vec4 val2 = getOneTextureValue(vec3(ijk.xy, ijk.z + zoff));\n\n float indexZ = float(volumeDimensions)*ijk.z;\n float zmix = indexZ - floor(indexZ);\n\n return mix(val1, val2, zmix);\n}\n\nvec4 getOneTextureValue(vec3 ijk)\n#else // nearest or fast linear\nvec4 getTextureValue(vec3 ijk)\n#endif\n{\n vec3 tdims = vec3(volumeDimensions);\n\n#ifdef debugtile\n vec2 tpos = vec2(ijk.x, ijk.y);\n vec4 tmp = texture2D(texture1, tpos);\n tmp.a = 1.0;\n\n#else\n int z = int(ijk.z * tdims.z);\n int yz = z / xreps;\n int xz = z - yz*xreps;\n\n int tileWidth = volumeDimensions.x/xstride;\n int tileHeight = volumeDimensions.y/ystride;\n\n xz *= tileWidth;\n yz *= tileHeight;\n\n float ni = float(xz) + (ijk.x*float(tileWidth));\n float nj = float(yz) + (ijk.y*float(tileHeight));\n\n vec2 tpos = vec2(ni/texWidth, nj/texHeight);\n\n vec4 tmp = texture2D(texture1, tpos);\n\n#if vtkNumComponents == 1\n tmp.a = tmp.r;\n#endif\n#if vtkNumComponents == 2\n tmp.g = tmp.a;\n#endif\n#if vtkNumComponents == 3\n tmp.a = length(tmp.rgb);\n#endif\n#endif\n\n return tmp;\n}\n\n// End of Webgl1 specific code\n//=======================================================================\n#endif\n\n//=======================================================================\n// compute the normal and gradient magnitude for a position\nvec4 computeNormal(vec3 pos, float scalar, vec3 tstep)\n{\n vec4 result;\n\n result.x = getTextureValue(pos + vec3(tstep.x, 0.0, 0.0)).a - scalar;\n result.y = getTextureValue(pos + vec3(0.0, tstep.y, 0.0)).a - scalar;\n result.z = getTextureValue(pos + vec3(0.0, 0.0, tstep.z)).a - scalar;\n\n // divide by spacing\n result.xyz /= vSpacing;\n\n result.w = length(result.xyz);\n\n // rotate to View Coords\n result.xyz =\n result.x * vPlaneNormal0 +\n result.y * vPlaneNormal2 +\n result.z * vPlaneNormal4;\n\n if (result.w > 0.0)\n {\n result.xyz /= result.w;\n }\n return result;\n}\n\n#ifdef vtkImageLabelOutlineOn\nvec3 fragCoordToIndexSpace(vec4 fragCoord) {\n vec4 pcPos = vec4(\n (fragCoord.x / vpWidth - 0.5) * 2.0,\n (fragCoord.y / vpHeight - 0.5) * 2.0,\n (fragCoord.z - 0.5) * 2.0,\n 1.0);\n\n vec4 worldCoord = PCWCMatrix * pcPos;\n vec4 vertex = (worldCoord/worldCoord.w);\n\n return (vWCtoIDX * vertex).xyz / vec3(volumeDimensions);\n}\n#endif\n\n//=======================================================================\n// compute the normals and gradient magnitudes for a position\n// for independent components\nmat4 computeMat4Normal(vec3 pos, vec4 tValue, vec3 tstep)\n{\n mat4 result;\n vec4 distX = getTextureValue(pos + vec3(tstep.x, 0.0, 0.0)) - tValue;\n vec4 distY = getTextureValue(pos + vec3(0.0, tstep.y, 0.0)) - tValue;\n vec4 distZ = getTextureValue(pos + vec3(0.0, 0.0, tstep.z)) - tValue;\n\n // divide by spacing\n distX /= vSpacing.x;\n distY /= vSpacing.y;\n distZ /= vSpacing.z;\n\n mat3 rot;\n rot[0] = vPlaneNormal0;\n rot[1] = vPlaneNormal2;\n rot[2] = vPlaneNormal4;\n\n#if !defined(vtkComponent0Proportional)\n result[0].xyz = vec3(distX.r, distY.r, distZ.r);\n result[0].a = length(result[0].xyz);\n result[0].xyz *= rot;\n if (result[0].w > 0.0)\n {\n result[0].xyz /= result[0].w;\n }\n#endif\n\n// optionally compute the 2nd component\n#if vtkNumComponents >= 2 && !defined(vtkComponent1Proportional)\n result[1].xyz = vec3(distX.g, distY.g, distZ.g);\n result[1].a = length(result[1].xyz);\n result[1].xyz *= rot;\n if (result[1].w > 0.0)\n {\n result[1].xyz /= result[1].w;\n }\n#endif\n\n// optionally compute the 3rd component\n#if vtkNumComponents >= 3 && !defined(vtkComponent2Proportional)\n result[2].xyz = vec3(distX.b, distY.b, distZ.b);\n result[2].a = length(result[2].xyz);\n result[2].xyz *= rot;\n if (result[2].w > 0.0)\n {\n result[2].xyz /= result[2].w;\n }\n#endif\n\n// optionally compute the 4th component\n#if vtkNumComponents >= 4 && !defined(vtkComponent3Proportional)\n result[3].xyz = vec3(distX.a, distY.a, distZ.a);\n result[3].a = length(result[3].xyz);\n result[3].xyz *= rot;\n if (result[3].w > 0.0)\n {\n result[3].xyz /= result[3].w;\n }\n#endif\n\n return result;\n}\n\n//=======================================================================\n// Given a normal compute the gradient opacity factors\n//\nfloat computeGradientOpacityFactor(\n vec4 normal, float goscale, float goshift, float gomin, float gomax)\n{\n#if defined(vtkGradientOpacityOn)\n return clamp(normal.a*goscale + goshift, gomin, gomax);\n#else\n return 1.0;\n#endif\n}\n\n#if vtkLightComplexity > 0\nvoid applyLighting(inout vec3 tColor, vec4 normal)\n{\n vec3 diffuse = vec3(0.0, 0.0, 0.0);\n vec3 specular = vec3(0.0, 0.0, 0.0);\n //VTK::Light::Impl\n tColor.rgb = tColor.rgb*(diffuse*vDiffuse + vAmbient) + specular*vSpecular;\n}\n#endif\n\n//=======================================================================\n// Given a texture value compute the color and opacity\n//\nvec4 getColorForValue(vec4 tValue, vec3 posIS, vec3 tstep)\n{\n#ifdef vtkImageLabelOutlineOn\n vec3 centerPosIS = fragCoordToIndexSpace(gl_FragCoord); // pos in texture space\n vec4 centerValue = getTextureValue(centerPosIS);\n bool pixelOnBorder = false;\n vec4 tColor = texture2D(ctexture, vec2(centerValue.r * cscale0 + cshift0, 0.5));\n\n // Get alpha of segment from opacity function.\n tColor.a = texture2D(otexture, vec2(centerValue.r * oscale0 + oshift0, 0.5)).r;\n\n // Only perform outline check on fragments rendering voxels that aren't invisible.\n // Saves a bunch of needless checks on the background.\n // TODO define epsilon when building shader?\n if (float(tColor.a) > 0.01) {\n for (int i = -outlineThickness; i <= outlineThickness; i++) {\n for (int j = -outlineThickness; j <= outlineThickness; j++) {\n if (i == 0 || j == 0) {\n continue;\n }\n\n vec4 neighborPixelCoord = vec4(gl_FragCoord.x + float(i),\n gl_FragCoord.y + float(j),\n gl_FragCoord.z, gl_FragCoord.w);\n\n vec3 neighborPosIS = fragCoordToIndexSpace(neighborPixelCoord);\n vec4 value = getTextureValue(neighborPosIS);\n\n // If any of my neighbours are not the same value as I\n // am, this means I am on the border of the segment.\n // We can break the loops\n if (any(notEqual(value, centerValue))) {\n pixelOnBorder = true;\n break;\n }\n }\n\n if (pixelOnBorder == true) {\n break;\n }\n }\n\n // If I am on the border, I am displayed at full opacity\n if (pixelOnBorder == true) {\n tColor.a = 1.0;\n }\n }\n\n#else\n // compute the normal and gradient magnitude if needed\n // We compute it as a vec4 if possible otherwise a mat4\n //\n vec4 goFactor = vec4(1.0,1.0,1.0,1.0);\n\n // compute the normal vectors as needed\n #if (vtkLightComplexity > 0) || defined(vtkGradientOpacityOn)\n #if defined(vtkIndependentComponentsOn) && (vtkNumComponents > 1)\n mat4 normalMat = computeMat4Normal(posIS, tValue, tstep);\n #if !defined(vtkComponent0Proportional)\n vec4 normal0 = normalMat[0];\n #endif\n #if !defined(vtkComponent1Proportional)\n vec4 normal1 = normalMat[1];\n #endif\n #if vtkNumComponents > 2\n #if !defined(vtkComponent2Proportional)\n vec4 normal2 = normalMat[2];\n #endif\n #if vtkNumComponents > 3\n #if !defined(vtkComponent3Proportional)\n vec4 normal3 = normalMat[3];\n #endif\n #endif\n #endif\n #else\n vec4 normal0 = computeNormal(posIS, tValue.a, tstep);\n #endif\n #endif\n\n // compute gradient opacity factors as needed\n #if defined(vtkGradientOpacityOn)\n #if !defined(vtkComponent0Proportional)\n goFactor.x =\n computeGradientOpacityFactor(normal0, goscale0, goshift0, gomin0, gomax0);\n #endif\n #if defined(vtkIndependentComponentsOn) && (vtkNumComponents > 1)\n #if !defined(vtkComponent1Proportional)\n goFactor.y =\n computeGradientOpacityFactor(normal1, goscale1, goshift1, gomin1, gomax1);\n #endif\n #if vtkNumComponents > 2\n #if !defined(vtkComponent2Proportional)\n goFactor.z =\n computeGradientOpacityFactor(normal2, goscale2, goshift2, gomin2, gomax2);\n #endif\n #if vtkNumComponents > 3\n #if !defined(vtkComponent3Proportional)\n goFactor.w =\n computeGradientOpacityFactor(normal3, goscale3, goshift3, gomin3, gomax3);\n #endif\n #endif\n #endif\n #endif\n #endif\n\n // single component is always independent\n #if vtkNumComponents == 1\n vec4 tColor = texture2D(ctexture, vec2(tValue.r * cscale0 + cshift0, 0.5));\n tColor.a = goFactor.x*texture2D(otexture, vec2(tValue.r * oscale0 + oshift0, 0.5)).r;\n #endif\n\n #if defined(vtkIndependentComponentsOn) && vtkNumComponents >= 2\n vec4 tColor = mix0*texture2D(ctexture, vec2(tValue.r * cscale0 + cshift0, height0));\n #if !defined(vtkComponent0Proportional)\n tColor.a = goFactor.x*mix0*texture2D(otexture, vec2(tValue.r * oscale0 + oshift0, height0)).r;\n #else\n float pwfValue = texture2D(otexture, vec2(tValue.r * oscale0 + oshift0, height0)).r;\n tColor *= pwfValue;\n tColor.a *= mix(pwfValue, 1.0, (1.0 - mix0));\n #endif\n\n vec3 tColor1 = mix1*texture2D(ctexture, vec2(tValue.g * cscale1 + cshift1, height1)).rgb;\n #if !defined(vtkComponent1Proportional)\n tColor.a += goFactor.y*mix1*texture2D(otexture, vec2(tValue.g * oscale1 + oshift1, height1)).r;\n #else\n float pwfValue = texture2D(otexture, vec2(tValue.g * oscale1 + oshift1, height1)).r;\n tColor1 *= pwfValue;\n tColor.a *= mix(pwfValue, 1.0, (1.0 - mix1));\n #endif\n\n #if vtkNumComponents >= 3\n vec3 tColor2 = mix2*texture2D(ctexture, vec2(tValue.b * cscale2 + cshift2, height2)).rgb;\n #if !defined(vtkComponent2Proportional)\n tColor.a += goFactor.z*mix2*texture2D(otexture, vec2(tValue.b * oscale2 + oshift2, height2)).r;\n #else\n float pwfValue = texture2D(otexture, vec2(tValue.b * oscale2 + oshift2, height2)).r;\n tColor2 *= pwfValue;\n tColor.a *= mix(pwfValue, 1.0, (1.0 - mix2));\n #endif\n\n #if vtkNumComponents >= 4\n vec3 tColor3 = mix3*texture2D(ctexture, vec2(tValue.a * cscale3 + cshift3, height3)).rgb;\n #if !defined(vtkComponent3Proportional)\n tColor.a += goFactor.w*mix3*texture2D(otexture, vec2(tValue.a * oscale3 + oshift3, height3)).r;\n #else\n float pwfValue = texture2D(otexture, vec2(tValue.a * oscale3 + oshift3, height3)).r;\n tColor3 *= pwfValue;\n tColor.a *= mix(pwfValue, 1.0, (1.0 - mix3));\n #endif\n #endif\n #endif\n #else // then not independent\n\n #if vtkNumComponents == 2\n float lum = tValue.r * cscale0 + cshift0;\n float alpha = goFactor.x*texture2D(otexture, vec2(tValue.a * oscale1 + oshift1, 0.5)).r;\n vec4 tColor = vec4(lum, lum, lum, alpha);\n #endif\n #if vtkNumComponents == 3\n vec4 tColor;\n tColor.r = tValue.r * cscale0 + cshift0;\n tColor.g = tValue.g * cscale1 + cshift1;\n tColor.b = tValue.b * cscale2 + cshift2;\n tColor.a = goFactor.x*texture2D(otexture, vec2(tValue.a * oscale0 + oshift0, 0.5)).r;\n #endif\n #if vtkNumComponents == 4\n vec4 tColor;\n tColor.r = tValue.r * cscale0 + cshift0;\n tColor.g = tValue.g * cscale1 + cshift1;\n tColor.b = tValue.b * cscale2 + cshift2;\n tColor.a = goFactor.x*texture2D(otexture, vec2(tValue.a * oscale3 + oshift3, 0.5)).r;\n #endif\n #endif // dependent\n\n // apply lighting if requested as appropriate\n #if vtkLightComplexity > 0\n #if !defined(vtkComponent0Proportional)\n applyLighting(tColor.rgb, normal0);\n #endif\n #if defined(vtkIndependentComponentsOn) && vtkNumComponents >= 2\n #if !defined(vtkComponent1Proportional)\n applyLighting(tColor1, normal1);\n #endif\n #if vtkNumComponents >= 3\n #if !defined(vtkComponent2Proportional)\n applyLighting(tColor2, normal2);\n #endif\n #if vtkNumComponents >= 4\n #if !defined(vtkComponent3Proportional)\n applyLighting(tColor3, normal3);\n #endif\n #endif\n #endif\n #endif\n#endif\n\n// perform final independent blend as needed\n#if defined(vtkIndependentComponentsOn) && vtkNumComponents >= 2\n tColor.rgb += tColor1;\n#if vtkNumComponents >= 3\n tColor.rgb += tColor2;\n#if vtkNumComponents >= 4\n tColor.rgb += tColor3;\n#endif\n#endif\n#endif\n\n#endif\n\n\n\n\n\n\n\nreturn tColor;\n}\n\nbool valueWithinScalarRange(vec4 val, vec4 min, vec4 max) {\n bool withinRange = false;\n #if vtkNumComponents == 1\n if (val.r >= min.r && val.r <= max.r) {\n withinRange = true;\n }\n #endif\n #if defined(vtkIndependentComponentsOn) && vtkNumComponents == 2\n if (val.r >= min.r && val.r <= max.r &&\n val.g >= min.g && val.g <= max.g) {\n withinRange = true;\n }\n #endif\n #if defined(vtkIndependentComponentsOn) && vtkNumComponents >= 3\n if (all(greaterThanEqual(val, ipScalarRangeMin)) &&\n all(lessThanEqual(val, ipScalarRangeMax))) {\n withinRange = true;\n }\n #endif\n return withinRange;\n}\n\n//=======================================================================\n// Apply the specified blend mode operation along the ray's path.\n//\nvoid applyBlend(vec3 posIS, vec3 endIS, float sampleDistanceIS, vec3 tdims)\n{\n vec3 tstep = 1.0/tdims;\n\n // start slightly inside and apply some jitter\n vec3 delta = endIS - posIS;\n vec3 stepIS = normalize(delta)*sampleDistanceIS;\n float raySteps = length(delta)/sampleDistanceIS;\n\n // avoid 0.0 jitter\n float jitter = 0.01 + 0.99*texture2D(jtexture, gl_FragCoord.xy/32.0).r;\n float stepsTraveled = jitter;\n\n // local vars for the loop\n vec4 color = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 tValue;\n vec4 tColor;\n\n // if we have less than one step then pick the middle point\n // as our value\n // if (raySteps <= 1.0)\n // {\n // posIS = (posIS + endIS)*0.5;\n // }\n\n // Perform initial step at the volume boundary\n // compute the scalar\n tValue = getTextureValue(posIS);\n\n #if vtkBlendMode == 0 // COMPOSITE_BLEND\n // now map through opacity and color\n tColor = getColorForValue(tValue, posIS, tstep);\n\n // handle very thin volumes\n if (raySteps <= 1.0)\n {\n tColor.a = 1.0 - pow(1.0 - tColor.a, raySteps);\n gl_FragData[0] = tColor;\n return;\n }\n\n tColor.a = 1.0 - pow(1.0 - tColor.a, jitter);\n color = vec4(tColor.rgb*tColor.a, tColor.a);\n posIS += (jitter*stepIS);\n\n for (int i = 0; i < //VTK::MaximumSamplesValue ; ++i)\n {\n if (stepsTraveled + 1.0 >= raySteps) { break; }\n\n // compute the scalar\n tValue = getTextureValue(posIS);\n\n // now map through opacity and color\n tColor = getColorForValue(tValue, posIS, tstep);\n\n float mix = (1.0 - color.a);\n\n // this line should not be needed but nvidia seems to not handle\n // the break correctly on windows/chrome 58 angle\n //mix = mix * sign(max(raySteps - stepsTraveled - 1.0, 0.0));\n\n color = color + vec4(tColor.rgb*tColor.a, tColor.a)*mix;\n stepsTraveled++;\n posIS += stepIS;\n if (color.a > 0.99) { color.a = 1.0; break; }\n }\n\n if (color.a < 0.99 && (raySteps - stepsTraveled) > 0.0)\n {\n posIS = endIS;\n\n // compute the scalar\n tValue = getTextureValue(posIS);\n\n // now map through opacity and color\n tColor = getColorForValue(tValue, posIS, tstep);\n tColor.a = 1.0 - pow(1.0 - tColor.a, raySteps - stepsTraveled);\n\n float mix = (1.0 - color.a);\n color = color + vec4(tColor.rgb*tColor.a, tColor.a)*mix;\n }\n\n gl_FragData[0] = vec4(color.rgb/color.a, color.a);\n #endif\n #if vtkBlendMode == 1 || vtkBlendMode == 2\n // MAXIMUM_INTENSITY_BLEND || MINIMUM_INTENSITY_BLEND\n // Find maximum/minimum intensity along the ray.\n\n // Define the operation we will use (min or max)\n #if vtkBlendMode == 1\n #define OP max\n #else\n #define OP min\n #endif\n\n // If the clipping range is shorter than the sample distance\n // we can skip the sampling loop along the ray.\n if (raySteps <= 1.0)\n {\n gl_FragData[0] = getColorForValue(tValue, posIS, tstep);\n return;\n }\n\n vec4 value = tValue;\n posIS += (jitter*stepIS);\n\n // Sample along the ray until MaximumSamplesValue,\n // ending slightly inside the total distance\n for (int i = 0; i < //VTK::MaximumSamplesValue ; ++i)\n {\n // If we have reached the last step, break\n if (stepsTraveled + 1.0 >= raySteps) { break; }\n\n // compute the scalar\n tValue = getTextureValue(posIS);\n\n // Update the maximum value if necessary\n value = OP(tValue, value);\n\n // Otherwise, continue along the ray\n stepsTraveled++;\n posIS += stepIS;\n }\n\n // Perform the last step along the ray using the\n // residual distance\n posIS = endIS;\n tValue = getTextureValue(posIS);\n value = OP(tValue, value);\n\n // Now map through opacity and color\n gl_FragData[0] = getColorForValue(value, posIS, tstep);\n #endif\n #if vtkBlendMode == 3 || vtkBlendMode == 4 //AVERAGE_INTENSITY_BLEND || ADDITIVE_BLEND\n vec4 sum = vec4(0.);\n\n if (valueWithinScalarRange(tValue, ipScalarRangeMin, ipScalarRangeMax)) {\n sum += tValue;\n }\n\n if (raySteps <= 1.0) {\n gl_FragData[0] = getColorForValue(sum, posIS, tstep);\n return;\n }\n\n posIS += (jitter*stepIS);\n\n // Sample along the ray until MaximumSamplesValue,\n // ending slightly inside the total distance\n for (int i = 0; i < //VTK::MaximumSamplesValue ; ++i)\n {\n // If we have reached the last step, break\n if (stepsTraveled + 1.0 >= raySteps) { break; }\n\n // compute the scalar\n tValue = getTextureValue(posIS);\n\n // One can control the scalar range by setting the AverageIPScalarRange to disregard scalar values, not in the range of interest, from the average computation.\n // Notes:\n // - We are comparing all values in the texture to see if any of them\n // are outside of the scalar range. In the future we might want to allow\n // scalar ranges for each component.\n if (valueWithinScalarRange(tValue, ipScalarRangeMin, ipScalarRangeMax)) {\n // Sum the values across each step in the path\n sum += tValue;\n }\n stepsTraveled++;\n posIS += stepIS;\n }\n\n // Perform the last step along the ray using the\n // residual distance\n posIS = endIS;\n\n // compute the scalar\n tValue = getTextureValue(posIS);\n\n // One can control the scalar range by setting the IPScalarRange to disregard scalar values, not in the range of interest, from the average computation\n if (valueWithinScalarRange(tValue, ipScalarRangeMin, ipScalarRangeMax)) {\n sum += tValue;\n\n stepsTraveled++;\n }\n\n #if vtkBlendMode == 3 // Average\n sum /= vec4(stepsTraveled, stepsTraveled, stepsTraveled, 1.0);\n #endif\n\n gl_FragData[0] = getColorForValue(sum, posIS, tstep);\n #endif\n}\n\n//=======================================================================\n// Compute a new start and end point for a given ray based\n// on the provided bounded clipping plane (aka a rectangle)\nvoid getRayPointIntersectionBounds(\n vec3 rayPos, vec3 rayDir,\n vec3 planeDir, float planeDist,\n inout vec2 tbounds, vec3 vPlaneX, vec3 vPlaneY,\n float vSize1, float vSize2)\n{\n float result = dot(rayDir, planeDir);\n if (abs(result) < 1e-6)\n {\n return;\n }\n result = -1.0 * (dot(rayPos, planeDir) + planeDist) / result;\n vec3 xposVC = rayPos + rayDir*result;\n vec3 vxpos = xposVC - vOriginVC;\n vec2 vpos = vec2(\n dot(vxpos, vPlaneX),\n dot(vxpos, vPlaneY));\n\n // on some apple nvidia systems this does not work\n // if (vpos.x < 0.0 || vpos.x > vSize1 ||\n // vpos.y < 0.0 || vpos.y > vSize2)\n // even just\n // if (vpos.x < 0.0 || vpos.y < 0.0)\n // fails\n // so instead we compute a value that represents in and out\n //and then compute the return using this value\n float xcheck = max(0.0, vpos.x * (vpos.x - vSize1)); // 0 means in bounds\n float check = sign(max(xcheck, vpos.y * (vpos.y - vSize2))); // 0 means in bounds, 1 = out\n\n tbounds = mix(\n vec2(min(tbounds.x, result), max(tbounds.y, result)), // in value\n tbounds, // out value\n check); // 0 in 1 out\n}\n\n//=======================================================================\n// given a\n// - ray direction (rayDir)\n// - starting point (vertexVCVSOutput)\n// - bounding planes of the volume\n// - optionally depth buffer values\n// - far clipping plane\n// compute the start/end distances of the ray we need to cast\nvec2 computeRayDistances(vec3 rayDir, vec3 tdims)\n{\n vec2 dists = vec2(100.0*camFar, -1.0);\n\n vec3 vSize = vSpacing*(tdims - 1.0);\n\n // all this is in View Coordinates\n getRayPointIntersectionBounds(vertexVCVSOutput, rayDir,\n vPlaneNormal0, vPlaneDistance0, dists, vPlaneNormal2, vPlaneNormal4,\n vSize.y, vSize.z);\n getRayPointIntersectionBounds(vertexVCVSOutput, rayDir,\n vPlaneNormal1, vPlaneDistance1, dists, vPlaneNormal2, vPlaneNormal4,\n vSize.y, vSize.z);\n getRayPointIntersectionBounds(vertexVCVSOutput, rayDir,\n vPlaneNormal2, vPlaneDistance2, dists, vPlaneNormal0, vPlaneNormal4,\n vSize.x, vSize.z);\n getRayPointIntersectionBounds(vertexVCVSOutput, rayDir,\n vPlaneNormal3, vPlaneDistance3, dists, vPlaneNormal0, vPlaneNormal4,\n vSize.x, vSize.z);\n getRayPointIntersectionBounds(vertexVCVSOutput, rayDir,\n vPlaneNormal4, vPlaneDistance4, dists, vPlaneNormal0, vPlaneNormal2,\n vSize.x, vSize.y);\n getRayPointIntersectionBounds(vertexVCVSOutput, rayDir,\n vPlaneNormal5, vPlaneDistance5, dists, vPlaneNormal0, vPlaneNormal2,\n vSize.x, vSize.y);\n\n //VTK::ClipPlane::Impl\n\n // do not go behind front clipping plane\n dists.x = max(0.0,dists.x);\n\n // do not go PAST far clipping plane\n float farDist = -camThick/rayDir.z;\n dists.y = min(farDist,dists.y);\n\n // Do not go past the zbuffer value if set\n // This is used for intermixing opaque geometry\n //VTK::ZBuffer::Impl\n\n return dists;\n}\n\n//=======================================================================\n// Compute the index space starting position (pos) and end\n// position\n//\nvoid computeIndexSpaceValues(out vec3 pos, out vec3 endPos, out float sampleDistanceIS, vec3 rayDir, vec2 dists)\n{\n // compute starting and ending values in volume space\n pos = vertexVCVSOutput + dists.x*rayDir;\n pos = pos - vOriginVC;\n // convert to volume basis and origin\n pos = vec3(\n dot(pos, vPlaneNormal0),\n dot(pos, vPlaneNormal2),\n dot(pos, vPlaneNormal4));\n\n endPos = vertexVCVSOutput + dists.y*rayDir;\n endPos = endPos - vOriginVC;\n endPos = vec3(\n dot(endPos, vPlaneNormal0),\n dot(endPos, vPlaneNormal2),\n dot(endPos, vPlaneNormal4));\n\n float delta = length(endPos - pos);\n\n pos *= vVCToIJK;\n endPos *= vVCToIJK;\n\n float delta2 = length(endPos - pos);\n sampleDistanceIS = sampleDistance*delta2/delta;\n}\n\nvoid main()\n{\n\n vec3 rayDirVC;\n\n if (cameraParallel == 1)\n {\n // Camera is parallel, so the rayDir is just the direction of the camera.\n rayDirVC = vec3(0.0, 0.0, -1.0);\n } else {\n // camera is at 0,0,0 so rayDir for perspective is just the vc coord\n rayDirVC = normalize(vertexVCVSOutput);\n }\n\n vec3 tdims = vec3(volumeDimensions);\n\n // compute the start and end points for the ray\n vec2 rayStartEndDistancesVC = computeRayDistances(rayDirVC, tdims);\n\n // do we need to composite? aka does the ray have any length\n // If not, bail out early\n if (rayStartEndDistancesVC.y <= rayStartEndDistancesVC.x)\n {\n discard;\n }\n\n // IS = Index Space\n vec3 posIS;\n vec3 endIS;\n float sampleDistanceIS;\n computeIndexSpaceValues(posIS, endIS, sampleDistanceIS, rayDirVC, rayStartEndDistancesVC);\n\n // Perform the blending operation along the ray\n applyBlend(posIS, endIS, sampleDistanceIS, tdims);\n}\n";
|
|
1
|
+
var vtkVolumeFS = "//VTK::System::Dec\n\n/*=========================================================================\n\n Program: Visualization Toolkit\n Module: vtkVolumeFS.glsl\n\n Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n All rights reserved.\n See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n\n This software is distributed WITHOUT ANY WARRANTY; without even\n the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n PURPOSE. See the above copyright notice for more information.\n\n=========================================================================*/\n// Template for the volume mappers fragment shader\n\n// the output of this shader\n//VTK::Output::Dec\n\nvarying vec3 vertexVCVSOutput;\n\n// first declare the settings from the mapper\n// that impact the code paths in here\n\n// always set vtkNumComponents 1,2,3,4\n//VTK::NumComponents\n\n// possibly define vtkTrilinearOn\n//VTK::TrilinearOn\n\n// possibly define vtkIndependentComponents\n//VTK::IndependentComponentsOn\n\n// possibly define any \"proportional\" components\n//VTK::vtkProportionalComponents\n\n// Define the blend mode to use\n#define vtkBlendMode //VTK::BlendMode\n\n// Possibly define vtkImageLabelOutlineOn\n//VTK::ImageLabelOutlineOn\n\n#ifdef vtkImageLabelOutlineOn\nuniform int outlineThickness;\nuniform float vpWidth;\nuniform float vpHeight;\nuniform float vpOffsetX;\nuniform float vpOffsetY;\nuniform mat4 PCWCMatrix;\nuniform mat4 vWCtoIDX;\n#endif\n\n// define vtkLightComplexity\n//VTK::LightComplexity\n#if vtkLightComplexity > 0\nuniform float vSpecularPower;\nuniform float vAmbient;\nuniform float vDiffuse;\nuniform float vSpecular;\n//VTK::Light::Dec\n#endif\n\n// possibly define vtkGradientOpacityOn\n//VTK::GradientOpacityOn\n#ifdef vtkGradientOpacityOn\nuniform float goscale0;\nuniform float goshift0;\nuniform float gomin0;\nuniform float gomax0;\n#if defined(vtkIndependentComponentsOn) && (vtkNumComponents > 1)\nuniform float goscale1;\nuniform float goshift1;\nuniform float gomin1;\nuniform float gomax1;\n#if vtkNumComponents >= 3\nuniform float goscale2;\nuniform float goshift2;\nuniform float gomin2;\nuniform float gomax2;\n#endif\n#if vtkNumComponents >= 4\nuniform float goscale3;\nuniform float goshift3;\nuniform float gomin3;\nuniform float gomax3;\n#endif\n#endif\n#endif\n\n// if you want to see the raw tiled\n// data in webgl1 uncomment the following line\n// #define debugtile\n\n// camera values\nuniform float camThick;\nuniform float camNear;\nuniform float camFar;\nuniform int cameraParallel;\n\n// values describing the volume geometry\nuniform vec3 vOriginVC;\nuniform vec3 vSpacing;\nuniform ivec3 volumeDimensions; // 3d texture dimensions\nuniform vec3 vPlaneNormal0;\nuniform float vPlaneDistance0;\nuniform vec3 vPlaneNormal1;\nuniform float vPlaneDistance1;\nuniform vec3 vPlaneNormal2;\nuniform float vPlaneDistance2;\nuniform vec3 vPlaneNormal3;\nuniform float vPlaneDistance3;\nuniform vec3 vPlaneNormal4;\nuniform float vPlaneDistance4;\nuniform vec3 vPlaneNormal5;\nuniform float vPlaneDistance5;\n\n//VTK::ClipPlane::Dec\n\n// opacity and color textures\nuniform sampler2D otexture;\nuniform float oshift0;\nuniform float oscale0;\nuniform sampler2D ctexture;\nuniform float cshift0;\nuniform float cscale0;\n\n// jitter texture\nuniform sampler2D jtexture;\n\n// some 3D texture values\nuniform float sampleDistance;\nuniform vec3 vVCToIJK;\n\n// the heights defined below are the locations\n// for the up to four components of the tfuns\n// the tfuns have a height of 2XnumComps pixels so the\n// values are computed to hit the middle of the two rows\n// for that component\n#ifdef vtkIndependentComponentsOn\n#if vtkNumComponents == 2\nuniform float mix0;\nuniform float mix1;\n#define height0 0.25\n#define height1 0.75\n#endif\n#if vtkNumComponents == 3\nuniform float mix0;\nuniform float mix1;\nuniform float mix2;\n#define height0 0.17\n#define height1 0.5\n#define height2 0.83\n#endif\n#if vtkNumComponents == 4\nuniform float mix0;\nuniform float mix1;\nuniform float mix2;\nuniform float mix3;\n#define height0 0.125\n#define height1 0.375\n#define height2 0.625\n#define height3 0.875\n#endif\n#endif\n\n#if vtkNumComponents >= 2\nuniform float oshift1;\nuniform float oscale1;\nuniform float cshift1;\nuniform float cscale1;\n#endif\n#if vtkNumComponents >= 3\nuniform float oshift2;\nuniform float oscale2;\nuniform float cshift2;\nuniform float cscale2;\n#endif\n#if vtkNumComponents >= 4\nuniform float oshift3;\nuniform float oscale3;\nuniform float cshift3;\nuniform float cscale3;\n#endif\n\nuniform vec4 ipScalarRangeMin;\nuniform vec4 ipScalarRangeMax;\n\n// declaration for intermixed geometry\n//VTK::ZBuffer::Dec\n\n// Lighting values\n//VTK::Light::Dec\n\n//=======================================================================\n// Webgl2 specific version of functions\n#if __VERSION__ == 300\n\nuniform highp sampler3D texture1;\n\nvec4 getTextureValue(vec3 pos)\n{\n vec4 tmp = texture(texture1, pos);\n#if vtkNumComponents == 1\n tmp.a = tmp.r;\n#endif\n#if vtkNumComponents == 2\n tmp.a = tmp.g;\n#endif\n#if vtkNumComponents == 3\n tmp.a = length(tmp.rgb);\n#endif\n return tmp;\n}\n\n//=======================================================================\n// WebGL1 specific version of functions\n#else\n\nuniform sampler2D texture1;\n\nuniform float texWidth;\nuniform float texHeight;\nuniform int xreps;\nuniform int xstride;\nuniform int ystride;\n\n// if computing trilinear values from multiple z slices\n#ifdef vtkTrilinearOn\nvec4 getTextureValue(vec3 ijk)\n{\n float zoff = 1.0/float(volumeDimensions.z);\n vec4 val1 = getOneTextureValue(ijk);\n vec4 val2 = getOneTextureValue(vec3(ijk.xy, ijk.z + zoff));\n\n float indexZ = float(volumeDimensions)*ijk.z;\n float zmix = indexZ - floor(indexZ);\n\n return mix(val1, val2, zmix);\n}\n\nvec4 getOneTextureValue(vec3 ijk)\n#else // nearest or fast linear\nvec4 getTextureValue(vec3 ijk)\n#endif\n{\n vec3 tdims = vec3(volumeDimensions);\n\n#ifdef debugtile\n vec2 tpos = vec2(ijk.x, ijk.y);\n vec4 tmp = texture2D(texture1, tpos);\n tmp.a = 1.0;\n\n#else\n int z = int(ijk.z * tdims.z);\n int yz = z / xreps;\n int xz = z - yz*xreps;\n\n int tileWidth = volumeDimensions.x/xstride;\n int tileHeight = volumeDimensions.y/ystride;\n\n xz *= tileWidth;\n yz *= tileHeight;\n\n float ni = float(xz) + (ijk.x*float(tileWidth));\n float nj = float(yz) + (ijk.y*float(tileHeight));\n\n vec2 tpos = vec2(ni/texWidth, nj/texHeight);\n\n vec4 tmp = texture2D(texture1, tpos);\n\n#if vtkNumComponents == 1\n tmp.a = tmp.r;\n#endif\n#if vtkNumComponents == 2\n tmp.g = tmp.a;\n#endif\n#if vtkNumComponents == 3\n tmp.a = length(tmp.rgb);\n#endif\n#endif\n\n return tmp;\n}\n\n// End of Webgl1 specific code\n//=======================================================================\n#endif\n\n//=======================================================================\n// compute the normal and gradient magnitude for a position\nvec4 computeNormal(vec3 pos, float scalar, vec3 tstep)\n{\n vec4 result;\n\n result.x = getTextureValue(pos + vec3(tstep.x, 0.0, 0.0)).a - scalar;\n result.y = getTextureValue(pos + vec3(0.0, tstep.y, 0.0)).a - scalar;\n result.z = getTextureValue(pos + vec3(0.0, 0.0, tstep.z)).a - scalar;\n\n // divide by spacing\n result.xyz /= vSpacing;\n\n result.w = length(result.xyz);\n\n // rotate to View Coords\n result.xyz =\n result.x * vPlaneNormal0 +\n result.y * vPlaneNormal2 +\n result.z * vPlaneNormal4;\n\n if (result.w > 0.0)\n {\n result.xyz /= result.w;\n }\n return result;\n}\n\n#ifdef vtkImageLabelOutlineOn\nvec3 fragCoordToIndexSpace(vec4 fragCoord) {\n vec4 pcPos = vec4(\n (fragCoord.x / vpWidth - vpOffsetX - 0.5) * 2.0,\n (fragCoord.y / vpHeight - vpOffsetY - 0.5) * 2.0,\n (fragCoord.z - 0.5) * 2.0,\n 1.0);\n\n vec4 worldCoord = PCWCMatrix * pcPos;\n vec4 vertex = (worldCoord/worldCoord.w);\n\n return (vWCtoIDX * vertex).xyz / vec3(volumeDimensions);\n}\n#endif\n\n//=======================================================================\n// compute the normals and gradient magnitudes for a position\n// for independent components\nmat4 computeMat4Normal(vec3 pos, vec4 tValue, vec3 tstep)\n{\n mat4 result;\n vec4 distX = getTextureValue(pos + vec3(tstep.x, 0.0, 0.0)) - tValue;\n vec4 distY = getTextureValue(pos + vec3(0.0, tstep.y, 0.0)) - tValue;\n vec4 distZ = getTextureValue(pos + vec3(0.0, 0.0, tstep.z)) - tValue;\n\n // divide by spacing\n distX /= vSpacing.x;\n distY /= vSpacing.y;\n distZ /= vSpacing.z;\n\n mat3 rot;\n rot[0] = vPlaneNormal0;\n rot[1] = vPlaneNormal2;\n rot[2] = vPlaneNormal4;\n\n#if !defined(vtkComponent0Proportional)\n result[0].xyz = vec3(distX.r, distY.r, distZ.r);\n result[0].a = length(result[0].xyz);\n result[0].xyz *= rot;\n if (result[0].w > 0.0)\n {\n result[0].xyz /= result[0].w;\n }\n#endif\n\n// optionally compute the 2nd component\n#if vtkNumComponents >= 2 && !defined(vtkComponent1Proportional)\n result[1].xyz = vec3(distX.g, distY.g, distZ.g);\n result[1].a = length(result[1].xyz);\n result[1].xyz *= rot;\n if (result[1].w > 0.0)\n {\n result[1].xyz /= result[1].w;\n }\n#endif\n\n// optionally compute the 3rd component\n#if vtkNumComponents >= 3 && !defined(vtkComponent2Proportional)\n result[2].xyz = vec3(distX.b, distY.b, distZ.b);\n result[2].a = length(result[2].xyz);\n result[2].xyz *= rot;\n if (result[2].w > 0.0)\n {\n result[2].xyz /= result[2].w;\n }\n#endif\n\n// optionally compute the 4th component\n#if vtkNumComponents >= 4 && !defined(vtkComponent3Proportional)\n result[3].xyz = vec3(distX.a, distY.a, distZ.a);\n result[3].a = length(result[3].xyz);\n result[3].xyz *= rot;\n if (result[3].w > 0.0)\n {\n result[3].xyz /= result[3].w;\n }\n#endif\n\n return result;\n}\n\n//=======================================================================\n// Given a normal compute the gradient opacity factors\n//\nfloat computeGradientOpacityFactor(\n vec4 normal, float goscale, float goshift, float gomin, float gomax)\n{\n#if defined(vtkGradientOpacityOn)\n return clamp(normal.a*goscale + goshift, gomin, gomax);\n#else\n return 1.0;\n#endif\n}\n\n#if vtkLightComplexity > 0\nvoid applyLighting(inout vec3 tColor, vec4 normal)\n{\n vec3 diffuse = vec3(0.0, 0.0, 0.0);\n vec3 specular = vec3(0.0, 0.0, 0.0);\n //VTK::Light::Impl\n tColor.rgb = tColor.rgb*(diffuse*vDiffuse + vAmbient) + specular*vSpecular;\n}\n#endif\n\n//=======================================================================\n// Given a texture value compute the color and opacity\n//\nvec4 getColorForValue(vec4 tValue, vec3 posIS, vec3 tstep)\n{\n#ifdef vtkImageLabelOutlineOn\n vec3 centerPosIS = fragCoordToIndexSpace(gl_FragCoord); // pos in texture space\n vec4 centerValue = getTextureValue(centerPosIS);\n bool pixelOnBorder = false;\n vec4 tColor = texture2D(ctexture, vec2(centerValue.r * cscale0 + cshift0, 0.5));\n\n // Get alpha of segment from opacity function.\n tColor.a = texture2D(otexture, vec2(centerValue.r * oscale0 + oshift0, 0.5)).r;\n\n // Only perform outline check on fragments rendering voxels that aren't invisible.\n // Saves a bunch of needless checks on the background.\n // TODO define epsilon when building shader?\n if (float(tColor.a) > 0.01) {\n for (int i = -outlineThickness; i <= outlineThickness; i++) {\n for (int j = -outlineThickness; j <= outlineThickness; j++) {\n if (i == 0 || j == 0) {\n continue;\n }\n\n vec4 neighborPixelCoord = vec4(gl_FragCoord.x + float(i),\n gl_FragCoord.y + float(j),\n gl_FragCoord.z, gl_FragCoord.w);\n\n vec3 neighborPosIS = fragCoordToIndexSpace(neighborPixelCoord);\n vec4 value = getTextureValue(neighborPosIS);\n\n // If any of my neighbours are not the same value as I\n // am, this means I am on the border of the segment.\n // We can break the loops\n if (any(notEqual(value, centerValue))) {\n pixelOnBorder = true;\n break;\n }\n }\n\n if (pixelOnBorder == true) {\n break;\n }\n }\n\n // If I am on the border, I am displayed at full opacity\n if (pixelOnBorder == true) {\n tColor.a = 1.0;\n }\n }\n\n#else\n // compute the normal and gradient magnitude if needed\n // We compute it as a vec4 if possible otherwise a mat4\n //\n vec4 goFactor = vec4(1.0,1.0,1.0,1.0);\n\n // compute the normal vectors as needed\n #if (vtkLightComplexity > 0) || defined(vtkGradientOpacityOn)\n #if defined(vtkIndependentComponentsOn) && (vtkNumComponents > 1)\n mat4 normalMat = computeMat4Normal(posIS, tValue, tstep);\n #if !defined(vtkComponent0Proportional)\n vec4 normal0 = normalMat[0];\n #endif\n #if !defined(vtkComponent1Proportional)\n vec4 normal1 = normalMat[1];\n #endif\n #if vtkNumComponents > 2\n #if !defined(vtkComponent2Proportional)\n vec4 normal2 = normalMat[2];\n #endif\n #if vtkNumComponents > 3\n #if !defined(vtkComponent3Proportional)\n vec4 normal3 = normalMat[3];\n #endif\n #endif\n #endif\n #else\n vec4 normal0 = computeNormal(posIS, tValue.a, tstep);\n #endif\n #endif\n\n // compute gradient opacity factors as needed\n #if defined(vtkGradientOpacityOn)\n #if !defined(vtkComponent0Proportional)\n goFactor.x =\n computeGradientOpacityFactor(normal0, goscale0, goshift0, gomin0, gomax0);\n #endif\n #if defined(vtkIndependentComponentsOn) && (vtkNumComponents > 1)\n #if !defined(vtkComponent1Proportional)\n goFactor.y =\n computeGradientOpacityFactor(normal1, goscale1, goshift1, gomin1, gomax1);\n #endif\n #if vtkNumComponents > 2\n #if !defined(vtkComponent2Proportional)\n goFactor.z =\n computeGradientOpacityFactor(normal2, goscale2, goshift2, gomin2, gomax2);\n #endif\n #if vtkNumComponents > 3\n #if !defined(vtkComponent3Proportional)\n goFactor.w =\n computeGradientOpacityFactor(normal3, goscale3, goshift3, gomin3, gomax3);\n #endif\n #endif\n #endif\n #endif\n #endif\n\n // single component is always independent\n #if vtkNumComponents == 1\n vec4 tColor = texture2D(ctexture, vec2(tValue.r * cscale0 + cshift0, 0.5));\n tColor.a = goFactor.x*texture2D(otexture, vec2(tValue.r * oscale0 + oshift0, 0.5)).r;\n #endif\n\n #if defined(vtkIndependentComponentsOn) && vtkNumComponents >= 2\n vec4 tColor = mix0*texture2D(ctexture, vec2(tValue.r * cscale0 + cshift0, height0));\n #if !defined(vtkComponent0Proportional)\n tColor.a = goFactor.x*mix0*texture2D(otexture, vec2(tValue.r * oscale0 + oshift0, height0)).r;\n #else\n float pwfValue = texture2D(otexture, vec2(tValue.r * oscale0 + oshift0, height0)).r;\n tColor *= pwfValue;\n tColor.a *= mix(pwfValue, 1.0, (1.0 - mix0));\n #endif\n\n vec3 tColor1 = mix1*texture2D(ctexture, vec2(tValue.g * cscale1 + cshift1, height1)).rgb;\n #if !defined(vtkComponent1Proportional)\n tColor.a += goFactor.y*mix1*texture2D(otexture, vec2(tValue.g * oscale1 + oshift1, height1)).r;\n #else\n float pwfValue = texture2D(otexture, vec2(tValue.g * oscale1 + oshift1, height1)).r;\n tColor1 *= pwfValue;\n tColor.a *= mix(pwfValue, 1.0, (1.0 - mix1));\n #endif\n\n #if vtkNumComponents >= 3\n vec3 tColor2 = mix2*texture2D(ctexture, vec2(tValue.b * cscale2 + cshift2, height2)).rgb;\n #if !defined(vtkComponent2Proportional)\n tColor.a += goFactor.z*mix2*texture2D(otexture, vec2(tValue.b * oscale2 + oshift2, height2)).r;\n #else\n float pwfValue = texture2D(otexture, vec2(tValue.b * oscale2 + oshift2, height2)).r;\n tColor2 *= pwfValue;\n tColor.a *= mix(pwfValue, 1.0, (1.0 - mix2));\n #endif\n\n #if vtkNumComponents >= 4\n vec3 tColor3 = mix3*texture2D(ctexture, vec2(tValue.a * cscale3 + cshift3, height3)).rgb;\n #if !defined(vtkComponent3Proportional)\n tColor.a += goFactor.w*mix3*texture2D(otexture, vec2(tValue.a * oscale3 + oshift3, height3)).r;\n #else\n float pwfValue = texture2D(otexture, vec2(tValue.a * oscale3 + oshift3, height3)).r;\n tColor3 *= pwfValue;\n tColor.a *= mix(pwfValue, 1.0, (1.0 - mix3));\n #endif\n #endif\n #endif\n #else // then not independent\n\n #if vtkNumComponents == 2\n float lum = tValue.r * cscale0 + cshift0;\n float alpha = goFactor.x*texture2D(otexture, vec2(tValue.a * oscale1 + oshift1, 0.5)).r;\n vec4 tColor = vec4(lum, lum, lum, alpha);\n #endif\n #if vtkNumComponents == 3\n vec4 tColor;\n tColor.r = tValue.r * cscale0 + cshift0;\n tColor.g = tValue.g * cscale1 + cshift1;\n tColor.b = tValue.b * cscale2 + cshift2;\n tColor.a = goFactor.x*texture2D(otexture, vec2(tValue.a * oscale0 + oshift0, 0.5)).r;\n #endif\n #if vtkNumComponents == 4\n vec4 tColor;\n tColor.r = tValue.r * cscale0 + cshift0;\n tColor.g = tValue.g * cscale1 + cshift1;\n tColor.b = tValue.b * cscale2 + cshift2;\n tColor.a = goFactor.x*texture2D(otexture, vec2(tValue.a * oscale3 + oshift3, 0.5)).r;\n #endif\n #endif // dependent\n\n // apply lighting if requested as appropriate\n #if vtkLightComplexity > 0\n #if !defined(vtkComponent0Proportional)\n applyLighting(tColor.rgb, normal0);\n #endif\n #if defined(vtkIndependentComponentsOn) && vtkNumComponents >= 2\n #if !defined(vtkComponent1Proportional)\n applyLighting(tColor1, normal1);\n #endif\n #if vtkNumComponents >= 3\n #if !defined(vtkComponent2Proportional)\n applyLighting(tColor2, normal2);\n #endif\n #if vtkNumComponents >= 4\n #if !defined(vtkComponent3Proportional)\n applyLighting(tColor3, normal3);\n #endif\n #endif\n #endif\n #endif\n#endif\n\n// perform final independent blend as needed\n#if defined(vtkIndependentComponentsOn) && vtkNumComponents >= 2\n tColor.rgb += tColor1;\n#if vtkNumComponents >= 3\n tColor.rgb += tColor2;\n#if vtkNumComponents >= 4\n tColor.rgb += tColor3;\n#endif\n#endif\n#endif\n\n#endif\n\n\n\n\n\n\n\nreturn tColor;\n}\n\nbool valueWithinScalarRange(vec4 val, vec4 min, vec4 max) {\n bool withinRange = false;\n #if vtkNumComponents == 1\n if (val.r >= min.r && val.r <= max.r) {\n withinRange = true;\n }\n #endif\n #if defined(vtkIndependentComponentsOn) && vtkNumComponents == 2\n if (val.r >= min.r && val.r <= max.r &&\n val.g >= min.g && val.g <= max.g) {\n withinRange = true;\n }\n #endif\n #if defined(vtkIndependentComponentsOn) && vtkNumComponents >= 3\n if (all(greaterThanEqual(val, ipScalarRangeMin)) &&\n all(lessThanEqual(val, ipScalarRangeMax))) {\n withinRange = true;\n }\n #endif\n return withinRange;\n}\n\n//=======================================================================\n// Apply the specified blend mode operation along the ray's path.\n//\nvoid applyBlend(vec3 posIS, vec3 endIS, float sampleDistanceIS, vec3 tdims)\n{\n vec3 tstep = 1.0/tdims;\n\n // start slightly inside and apply some jitter\n vec3 delta = endIS - posIS;\n vec3 stepIS = normalize(delta)*sampleDistanceIS;\n float raySteps = length(delta)/sampleDistanceIS;\n\n // avoid 0.0 jitter\n float jitter = 0.01 + 0.99*texture2D(jtexture, gl_FragCoord.xy/32.0).r;\n float stepsTraveled = jitter;\n\n // local vars for the loop\n vec4 color = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 tValue;\n vec4 tColor;\n\n // if we have less than one step then pick the middle point\n // as our value\n // if (raySteps <= 1.0)\n // {\n // posIS = (posIS + endIS)*0.5;\n // }\n\n // Perform initial step at the volume boundary\n // compute the scalar\n tValue = getTextureValue(posIS);\n\n #if vtkBlendMode == 0 // COMPOSITE_BLEND\n // now map through opacity and color\n tColor = getColorForValue(tValue, posIS, tstep);\n\n // handle very thin volumes\n if (raySteps <= 1.0)\n {\n tColor.a = 1.0 - pow(1.0 - tColor.a, raySteps);\n gl_FragData[0] = tColor;\n return;\n }\n\n tColor.a = 1.0 - pow(1.0 - tColor.a, jitter);\n color = vec4(tColor.rgb*tColor.a, tColor.a);\n posIS += (jitter*stepIS);\n\n for (int i = 0; i < //VTK::MaximumSamplesValue ; ++i)\n {\n if (stepsTraveled + 1.0 >= raySteps) { break; }\n\n // compute the scalar\n tValue = getTextureValue(posIS);\n\n // now map through opacity and color\n tColor = getColorForValue(tValue, posIS, tstep);\n\n float mix = (1.0 - color.a);\n\n // this line should not be needed but nvidia seems to not handle\n // the break correctly on windows/chrome 58 angle\n //mix = mix * sign(max(raySteps - stepsTraveled - 1.0, 0.0));\n\n color = color + vec4(tColor.rgb*tColor.a, tColor.a)*mix;\n stepsTraveled++;\n posIS += stepIS;\n if (color.a > 0.99) { color.a = 1.0; break; }\n }\n\n if (color.a < 0.99 && (raySteps - stepsTraveled) > 0.0)\n {\n posIS = endIS;\n\n // compute the scalar\n tValue = getTextureValue(posIS);\n\n // now map through opacity and color\n tColor = getColorForValue(tValue, posIS, tstep);\n tColor.a = 1.0 - pow(1.0 - tColor.a, raySteps - stepsTraveled);\n\n float mix = (1.0 - color.a);\n color = color + vec4(tColor.rgb*tColor.a, tColor.a)*mix;\n }\n\n gl_FragData[0] = vec4(color.rgb/color.a, color.a);\n #endif\n #if vtkBlendMode == 1 || vtkBlendMode == 2\n // MAXIMUM_INTENSITY_BLEND || MINIMUM_INTENSITY_BLEND\n // Find maximum/minimum intensity along the ray.\n\n // Define the operation we will use (min or max)\n #if vtkBlendMode == 1\n #define OP max\n #else\n #define OP min\n #endif\n\n // If the clipping range is shorter than the sample distance\n // we can skip the sampling loop along the ray.\n if (raySteps <= 1.0)\n {\n gl_FragData[0] = getColorForValue(tValue, posIS, tstep);\n return;\n }\n\n vec4 value = tValue;\n posIS += (jitter*stepIS);\n\n // Sample along the ray until MaximumSamplesValue,\n // ending slightly inside the total distance\n for (int i = 0; i < //VTK::MaximumSamplesValue ; ++i)\n {\n // If we have reached the last step, break\n if (stepsTraveled + 1.0 >= raySteps) { break; }\n\n // compute the scalar\n tValue = getTextureValue(posIS);\n\n // Update the maximum value if necessary\n value = OP(tValue, value);\n\n // Otherwise, continue along the ray\n stepsTraveled++;\n posIS += stepIS;\n }\n\n // Perform the last step along the ray using the\n // residual distance\n posIS = endIS;\n tValue = getTextureValue(posIS);\n value = OP(tValue, value);\n\n // Now map through opacity and color\n gl_FragData[0] = getColorForValue(value, posIS, tstep);\n #endif\n #if vtkBlendMode == 3 || vtkBlendMode == 4 //AVERAGE_INTENSITY_BLEND || ADDITIVE_BLEND\n vec4 sum = vec4(0.);\n\n if (valueWithinScalarRange(tValue, ipScalarRangeMin, ipScalarRangeMax)) {\n sum += tValue;\n }\n\n if (raySteps <= 1.0) {\n gl_FragData[0] = getColorForValue(sum, posIS, tstep);\n return;\n }\n\n posIS += (jitter*stepIS);\n\n // Sample along the ray until MaximumSamplesValue,\n // ending slightly inside the total distance\n for (int i = 0; i < //VTK::MaximumSamplesValue ; ++i)\n {\n // If we have reached the last step, break\n if (stepsTraveled + 1.0 >= raySteps) { break; }\n\n // compute the scalar\n tValue = getTextureValue(posIS);\n\n // One can control the scalar range by setting the AverageIPScalarRange to disregard scalar values, not in the range of interest, from the average computation.\n // Notes:\n // - We are comparing all values in the texture to see if any of them\n // are outside of the scalar range. In the future we might want to allow\n // scalar ranges for each component.\n if (valueWithinScalarRange(tValue, ipScalarRangeMin, ipScalarRangeMax)) {\n // Sum the values across each step in the path\n sum += tValue;\n }\n stepsTraveled++;\n posIS += stepIS;\n }\n\n // Perform the last step along the ray using the\n // residual distance\n posIS = endIS;\n\n // compute the scalar\n tValue = getTextureValue(posIS);\n\n // One can control the scalar range by setting the IPScalarRange to disregard scalar values, not in the range of interest, from the average computation\n if (valueWithinScalarRange(tValue, ipScalarRangeMin, ipScalarRangeMax)) {\n sum += tValue;\n\n stepsTraveled++;\n }\n\n #if vtkBlendMode == 3 // Average\n sum /= vec4(stepsTraveled, stepsTraveled, stepsTraveled, 1.0);\n #endif\n\n gl_FragData[0] = getColorForValue(sum, posIS, tstep);\n #endif\n}\n\n//=======================================================================\n// Compute a new start and end point for a given ray based\n// on the provided bounded clipping plane (aka a rectangle)\nvoid getRayPointIntersectionBounds(\n vec3 rayPos, vec3 rayDir,\n vec3 planeDir, float planeDist,\n inout vec2 tbounds, vec3 vPlaneX, vec3 vPlaneY,\n float vSize1, float vSize2)\n{\n float result = dot(rayDir, planeDir);\n if (abs(result) < 1e-6)\n {\n return;\n }\n result = -1.0 * (dot(rayPos, planeDir) + planeDist) / result;\n vec3 xposVC = rayPos + rayDir*result;\n vec3 vxpos = xposVC - vOriginVC;\n vec2 vpos = vec2(\n dot(vxpos, vPlaneX),\n dot(vxpos, vPlaneY));\n\n // on some apple nvidia systems this does not work\n // if (vpos.x < 0.0 || vpos.x > vSize1 ||\n // vpos.y < 0.0 || vpos.y > vSize2)\n // even just\n // if (vpos.x < 0.0 || vpos.y < 0.0)\n // fails\n // so instead we compute a value that represents in and out\n //and then compute the return using this value\n float xcheck = max(0.0, vpos.x * (vpos.x - vSize1)); // 0 means in bounds\n float check = sign(max(xcheck, vpos.y * (vpos.y - vSize2))); // 0 means in bounds, 1 = out\n\n tbounds = mix(\n vec2(min(tbounds.x, result), max(tbounds.y, result)), // in value\n tbounds, // out value\n check); // 0 in 1 out\n}\n\n//=======================================================================\n// given a\n// - ray direction (rayDir)\n// - starting point (vertexVCVSOutput)\n// - bounding planes of the volume\n// - optionally depth buffer values\n// - far clipping plane\n// compute the start/end distances of the ray we need to cast\nvec2 computeRayDistances(vec3 rayDir, vec3 tdims)\n{\n vec2 dists = vec2(100.0*camFar, -1.0);\n\n vec3 vSize = vSpacing*(tdims - 1.0);\n\n // all this is in View Coordinates\n getRayPointIntersectionBounds(vertexVCVSOutput, rayDir,\n vPlaneNormal0, vPlaneDistance0, dists, vPlaneNormal2, vPlaneNormal4,\n vSize.y, vSize.z);\n getRayPointIntersectionBounds(vertexVCVSOutput, rayDir,\n vPlaneNormal1, vPlaneDistance1, dists, vPlaneNormal2, vPlaneNormal4,\n vSize.y, vSize.z);\n getRayPointIntersectionBounds(vertexVCVSOutput, rayDir,\n vPlaneNormal2, vPlaneDistance2, dists, vPlaneNormal0, vPlaneNormal4,\n vSize.x, vSize.z);\n getRayPointIntersectionBounds(vertexVCVSOutput, rayDir,\n vPlaneNormal3, vPlaneDistance3, dists, vPlaneNormal0, vPlaneNormal4,\n vSize.x, vSize.z);\n getRayPointIntersectionBounds(vertexVCVSOutput, rayDir,\n vPlaneNormal4, vPlaneDistance4, dists, vPlaneNormal0, vPlaneNormal2,\n vSize.x, vSize.y);\n getRayPointIntersectionBounds(vertexVCVSOutput, rayDir,\n vPlaneNormal5, vPlaneDistance5, dists, vPlaneNormal0, vPlaneNormal2,\n vSize.x, vSize.y);\n\n //VTK::ClipPlane::Impl\n\n // do not go behind front clipping plane\n dists.x = max(0.0,dists.x);\n\n // do not go PAST far clipping plane\n float farDist = -camThick/rayDir.z;\n dists.y = min(farDist,dists.y);\n\n // Do not go past the zbuffer value if set\n // This is used for intermixing opaque geometry\n //VTK::ZBuffer::Impl\n\n return dists;\n}\n\n//=======================================================================\n// Compute the index space starting position (pos) and end\n// position\n//\nvoid computeIndexSpaceValues(out vec3 pos, out vec3 endPos, out float sampleDistanceIS, vec3 rayDir, vec2 dists)\n{\n // compute starting and ending values in volume space\n pos = vertexVCVSOutput + dists.x*rayDir;\n pos = pos - vOriginVC;\n // convert to volume basis and origin\n pos = vec3(\n dot(pos, vPlaneNormal0),\n dot(pos, vPlaneNormal2),\n dot(pos, vPlaneNormal4));\n\n endPos = vertexVCVSOutput + dists.y*rayDir;\n endPos = endPos - vOriginVC;\n endPos = vec3(\n dot(endPos, vPlaneNormal0),\n dot(endPos, vPlaneNormal2),\n dot(endPos, vPlaneNormal4));\n\n float delta = length(endPos - pos);\n\n pos *= vVCToIJK;\n endPos *= vVCToIJK;\n\n float delta2 = length(endPos - pos);\n sampleDistanceIS = sampleDistance*delta2/delta;\n}\n\nvoid main()\n{\n\n vec3 rayDirVC;\n\n if (cameraParallel == 1)\n {\n // Camera is parallel, so the rayDir is just the direction of the camera.\n rayDirVC = vec3(0.0, 0.0, -1.0);\n } else {\n // camera is at 0,0,0 so rayDir for perspective is just the vc coord\n rayDirVC = normalize(vertexVCVSOutput);\n }\n\n vec3 tdims = vec3(volumeDimensions);\n\n // compute the start and end points for the ray\n vec2 rayStartEndDistancesVC = computeRayDistances(rayDirVC, tdims);\n\n // do we need to composite? aka does the ray have any length\n // If not, bail out early\n if (rayStartEndDistancesVC.y <= rayStartEndDistancesVC.x)\n {\n discard;\n }\n\n // IS = Index Space\n vec3 posIS;\n vec3 endIS;\n float sampleDistanceIS;\n computeIndexSpaceValues(posIS, endIS, sampleDistanceIS, rayDirVC, rayStartEndDistancesVC);\n\n // Perform the blending operation along the ray\n applyBlend(posIS, endIS, sampleDistanceIS, tdims);\n}\n";
|
|
2
2
|
|
|
3
3
|
export { vtkVolumeFS as v };
|
|
@@ -183,7 +183,7 @@ function vtkWebGPUImageMapper(publicAPI, model) {
|
|
|
183
183
|
var target = iComps ? i : 0;
|
|
184
184
|
var cfun = actor.getProperty().getRGBTransferFunction(target);
|
|
185
185
|
|
|
186
|
-
if (cfun) {
|
|
186
|
+
if (cfun && actor.getProperty().getUseLookupTableScalarRange()) {
|
|
187
187
|
var cRange = cfun.getRange();
|
|
188
188
|
cw = cRange[1] - cRange[0];
|
|
189
189
|
cl = 0.5 * (cRange[1] + cRange[0]);
|