@kitware/vtk.js 23.4.0 → 24.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BREAKING_CHANGES.md +33 -0
- package/Common/Core/DataArray.js +4 -0
- package/Common/Core/Math/index.js +2 -2
- package/Common/Core/Math.js +1 -1
- package/Common/DataModel/BoundingBox.js +3 -8
- package/Common/DataModel/DataSetAttributes/FieldData.js +9 -5
- package/Common/DataModel/ITKHelper.js +2 -346
- package/Common/DataModel/ImageData.d.ts +23 -6
- package/Common/DataModel/ImageData.js +8 -1
- package/Common/DataModel/PolyData.d.ts +8 -1
- package/Common/DataModel/PolyData.js +5 -3
- package/Common/DataModel/Triangle.js +217 -2
- package/Common/Transform/LandmarkTransform.js +1 -1
- package/Filters/General/OBBTree/OBBNode.js +82 -0
- package/Filters/General/OBBTree/helper.js +92 -0
- package/Filters/General/OBBTree.js +1249 -0
- package/Filters/General/WindowedSincPolyDataFilter.js +1 -1
- package/Filters/General.js +2 -0
- package/Filters/Sources/CircleSource.js +1 -1
- package/Filters/Sources/PointSource.js +1 -1
- package/Filters/Texture/TextureMapToPlane.js +1 -1
- package/Interaction/Manipulators/KeyboardCameraManipulator.js +1 -1
- package/Interaction/Manipulators/MouseCameraTrackballRollManipulator.js +1 -1
- package/Interaction/Manipulators/MouseCameraTrackballRotateManipulator.js +1 -1
- package/Interaction/Manipulators/MouseCameraUnicamManipulator.js +1 -1
- package/Interaction/Manipulators/MouseCameraUnicamRotateManipulator.js +1 -1
- package/Interaction/Style/InteractorStyleImage.js +3 -3
- package/Interaction/Style/InteractorStyleMPRSlice.js +12 -6
- package/Interaction/Style/InteractorStyleManipulator.js +42 -28
- package/Interaction/Style/InteractorStyleRemoteMouse.js +32 -14
- package/Interaction/Style/InteractorStyleTrackballCamera.js +7 -7
- package/Interaction/Widgets/OrientationMarkerWidget.js +18 -13
- package/Interaction/Widgets/PiecewiseGaussianWidget.js +1 -1
- package/Interaction/Widgets.js +1 -35
- package/Proxy/Core/View2DProxy.js +1 -1
- package/Rendering/Core/ColorTransferFunction.js +1 -1
- package/Rendering/Core/Coordinate.js +1 -1
- package/Rendering/Core/CubeAxesActor.js +1 -1
- package/Rendering/Core/Glyph3DMapper.js +1 -1
- package/Rendering/Core/ImageMapper.js +1 -1
- package/Rendering/Core/InteractorObserver.js +11 -10
- package/Rendering/Core/InteractorStyle.js +9 -4
- package/Rendering/Core/Mapper.js +1 -1
- package/Rendering/Core/Prop.js +6 -4
- package/Rendering/Core/Prop3D.js +1 -1
- package/Rendering/Core/RenderWindowInteractor.js +24 -17
- package/Rendering/Core/Renderer.js +24 -19
- package/Rendering/Core/ScalarBarActor.js +1 -1
- package/Rendering/Core/Viewport.js +1 -1
- package/Rendering/Core/VolumeMapper.js +1 -1
- package/Rendering/OpenGL/Actor.js +2 -2
- package/Rendering/OpenGL/Actor2D.js +2 -2
- package/Rendering/OpenGL/BufferObject.js +6 -5
- package/Rendering/OpenGL/Camera.js +3 -3
- package/Rendering/OpenGL/CellArrayBufferObject.js +1 -1
- package/Rendering/OpenGL/Framebuffer.js +13 -12
- package/Rendering/OpenGL/Glyph3DMapper.js +10 -8
- package/Rendering/OpenGL/HardwareSelector.js +35 -25
- package/Rendering/OpenGL/ImageMapper.js +51 -45
- package/Rendering/OpenGL/ImageSlice.js +2 -2
- package/Rendering/OpenGL/PixelSpaceCallbackMapper.js +4 -2
- package/Rendering/OpenGL/PolyDataMapper.js +14 -11
- package/Rendering/OpenGL/PolyDataMapper2D.js +17 -16
- package/Rendering/OpenGL/Renderer.js +11 -7
- package/Rendering/OpenGL/ReplacementShaderMapper.js +1 -1
- package/Rendering/OpenGL/ScalarBarActor.js +2 -2
- package/Rendering/OpenGL/ShaderCache.js +7 -5
- package/Rendering/OpenGL/Skybox.js +11 -9
- package/Rendering/OpenGL/SphereMapper.js +2 -2
- package/Rendering/OpenGL/StickMapper.js +2 -2
- package/Rendering/OpenGL/SurfaceLIC/LineIntegralConvolution2D/pingpong.js +13 -12
- package/Rendering/OpenGL/SurfaceLIC/LineIntegralConvolution2D.js +11 -9
- package/Rendering/OpenGL/SurfaceLIC/SurfaceLICInterface.js +19 -12
- package/Rendering/OpenGL/SurfaceLIC/SurfaceLICMapper.js +9 -6
- package/Rendering/OpenGL/Texture.js +44 -31
- package/Rendering/OpenGL/VertexArrayObject.js +7 -7
- package/Rendering/OpenGL/Volume.js +3 -2
- package/Rendering/OpenGL/VolumeMapper.js +30 -26
- package/Rendering/OpenGL/glsl/vtkVolumeFS.glsl.js +1 -1
- package/Rendering/SceneGraph/ViewNode.js +8 -7
- package/Rendering/WebGPU/Renderer.js +18 -10
- package/Widgets/Core/AbstractWidget.js +5 -4
- package/Widgets/Core/AbstractWidgetFactory.js +2 -1
- package/Widgets/Core/WidgetManager.js +66 -49
- package/Widgets/Manipulators/LineManipulator.js +1 -1
- package/Widgets/Representations/CircleContextRepresentation.js +1 -1
- package/Widgets/Representations/ImplicitPlaneRepresentation.js +5 -5
- package/Widgets/Representations/PolyLineRepresentation.js +1 -1
- package/Widgets/Representations/ResliceCursorContextRepresentation.js +7 -7
- package/Widgets/SVG/SVGLandmarkRepresentation/Constants.js +2 -2
- package/Widgets/SVG/SVGLandmarkRepresentation.js +21 -8
- package/Widgets/SVG/SVGRepresentation.js +1 -1
- package/Widgets/Widgets3D/AngleWidget/behavior.js +14 -6
- package/Widgets/Widgets3D/DistanceWidget/behavior.js +14 -6
- package/Widgets/Widgets3D/EllipseWidget.js +0 -1
- package/Widgets/Widgets3D/ImageCroppingWidget/behavior.js +6 -2
- package/Widgets/Widgets3D/ImplicitPlaneWidget.js +4 -2
- package/Widgets/Widgets3D/LabelWidget/behavior.js +138 -0
- package/Widgets/Widgets3D/LabelWidget/state.js +22 -0
- package/Widgets/Widgets3D/LabelWidget.js +79 -0
- package/Widgets/Widgets3D/LineWidget/behavior.js +18 -9
- package/Widgets/Widgets3D/LineWidget/helpers.js +1 -1
- package/Widgets/Widgets3D/LineWidget.js +0 -1
- package/Widgets/Widgets3D/PaintWidget/behavior.js +5 -3
- package/Widgets/Widgets3D/PolyLineWidget/behavior.js +18 -8
- package/Widgets/Widgets3D/RectangleWidget.js +0 -1
- package/Widgets/Widgets3D/ResliceCursorWidget/behavior.js +1 -1
- package/Widgets/Widgets3D/ResliceCursorWidget/helpers.js +1 -1
- package/Widgets/Widgets3D/ResliceCursorWidget.js +1 -1
- package/Widgets/Widgets3D/ShapeWidget/behavior.js +18 -11
- package/Widgets/Widgets3D/SplineWidget/behavior.js +33 -21
- package/index.d.ts +3 -4
- package/interfaces.d.ts +11 -0
- package/macros.d.ts +26 -1
- package/macros.js +51 -19
- package/package.json +1 -1
- package/types.d.ts +1 -0
- package/Interaction/Widgets/AbstractWidget.js +0 -104
- package/Interaction/Widgets/DistanceRepresentation.js +0 -116
- package/Interaction/Widgets/DistanceWidget.js +0 -77
- package/Interaction/Widgets/HandleRepresentation/Constants.js +0 -12
- package/Interaction/Widgets/HandleRepresentation.js +0 -100
- package/Interaction/Widgets/HandleWidget/Constants.js +0 -9
- package/Interaction/Widgets/HandleWidget.js +0 -194
- package/Interaction/Widgets/ImageCroppingRegionsRepresentation.js +0 -233
- package/Interaction/Widgets/ImageCroppingRegionsWidget/Constants.js +0 -16
- package/Interaction/Widgets/ImageCroppingRegionsWidget.js +0 -573
- package/Interaction/Widgets/LabelRepresentation/Constants.js +0 -17
- package/Interaction/Widgets/LabelRepresentation.js +0 -325
- package/Interaction/Widgets/LabelWidget.js +0 -65
- package/Interaction/Widgets/LineRepresentation/Constants.js +0 -21
- package/Interaction/Widgets/LineRepresentation.js +0 -498
- package/Interaction/Widgets/LineWidget/Constants.js +0 -11
- package/Interaction/Widgets/LineWidget.js +0 -296
- package/Interaction/Widgets/PointPlacer.js +0 -51
- package/Interaction/Widgets/ResliceCursor/ResliceCursor/Constants.js +0 -10
- package/Interaction/Widgets/ResliceCursor/ResliceCursor.js +0 -269
- package/Interaction/Widgets/ResliceCursor/ResliceCursorActor/Constants.js +0 -10
- package/Interaction/Widgets/ResliceCursor/ResliceCursorActor.js +0 -146
- package/Interaction/Widgets/ResliceCursor/ResliceCursorLineRepresentation.js +0 -332
- package/Interaction/Widgets/ResliceCursor/ResliceCursorPolyDataAlgorithm.js +0 -134
- package/Interaction/Widgets/ResliceCursor/ResliceCursorRepresentation/Constants.js +0 -16
- package/Interaction/Widgets/ResliceCursor/ResliceCursorRepresentation.js +0 -371
- package/Interaction/Widgets/ResliceCursor/ResliceCursorWidget/Constants.js +0 -10
- package/Interaction/Widgets/ResliceCursor/ResliceCursorWidget.js +0 -157
- package/Interaction/Widgets/SphereHandleRepresentation.js +0 -370
- package/Interaction/Widgets/WidgetRepresentation.js +0 -121
- package/Widgets/Representations/SphereContextRepresentation.js +0 -131
- package/Widgets/Widgets3D/SphereWidget/behavior.js +0 -177
- package/Widgets/Widgets3D/SphereWidget/state.js +0 -45
- package/Widgets/Widgets3D/SphereWidget.d.ts +0 -50
- package/Widgets/Widgets3D/SphereWidget.js +0 -62
|
@@ -3,7 +3,7 @@ import Constants from './Texture/Constants.js';
|
|
|
3
3
|
import HalfFloat from '../../Common/Core/HalfFloat.js';
|
|
4
4
|
import { newInstance as newInstance$1, obj, set, setGet, get, newTypedArray, vtkDebugMacro as vtkDebugMacro$1, vtkErrorMacro as vtkErrorMacro$1, vtkWarningMacro as vtkWarningMacro$1 } from '../../macros.js';
|
|
5
5
|
import vtkDataArray from '../../Common/Core/DataArray.js';
|
|
6
|
-
import {
|
|
6
|
+
import { Q as isPowerOfTwo, M as nearestPowerOfTwo } from '../../Common/Core/Math/index.js';
|
|
7
7
|
import vtkViewNode from '../SceneGraph/ViewNode.js';
|
|
8
8
|
import { registerOverride } from './ViewNodeFactory.js';
|
|
9
9
|
|
|
@@ -29,14 +29,14 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
29
29
|
var renWin = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
30
30
|
|
|
31
31
|
if (renWin) {
|
|
32
|
-
model.
|
|
32
|
+
model._openGLRenderWindow = renWin;
|
|
33
33
|
} else {
|
|
34
34
|
model.openGLRenderer = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderer'); // sync renderable properties
|
|
35
35
|
|
|
36
|
-
model.
|
|
36
|
+
model._openGLRenderWindow = model.openGLRenderer.getParent();
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
model.context = model.
|
|
39
|
+
model.context = model._openGLRenderWindow.getContext();
|
|
40
40
|
|
|
41
41
|
if (model.renderable.getInterpolate()) {
|
|
42
42
|
if (model.generateMipmap) {
|
|
@@ -184,7 +184,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
184
184
|
model.context.texParameteri(model.target, model.context.TEXTURE_WRAP_S, publicAPI.getOpenGLWrapMode(model.wrapS));
|
|
185
185
|
model.context.texParameteri(model.target, model.context.TEXTURE_WRAP_T, publicAPI.getOpenGLWrapMode(model.wrapT));
|
|
186
186
|
|
|
187
|
-
if (model.
|
|
187
|
+
if (model._openGLRenderWindow.getWebgl2()) {
|
|
188
188
|
model.context.texParameteri(model.target, model.context.TEXTURE_WRAP_R, publicAPI.getOpenGLWrapMode(model.wrapR));
|
|
189
189
|
}
|
|
190
190
|
|
|
@@ -195,8 +195,8 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
195
195
|
|
|
196
196
|
|
|
197
197
|
publicAPI.getTextureUnit = function () {
|
|
198
|
-
if (model.
|
|
199
|
-
return model.
|
|
198
|
+
if (model._openGLRenderWindow) {
|
|
199
|
+
return model._openGLRenderWindow.getTextureUnitForTexture(publicAPI);
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
return -1;
|
|
@@ -205,14 +205,15 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
205
205
|
|
|
206
206
|
publicAPI.activate = function () {
|
|
207
207
|
// activate a free texture unit for this texture
|
|
208
|
-
model.
|
|
208
|
+
model._openGLRenderWindow.activateTexture(publicAPI);
|
|
209
|
+
|
|
209
210
|
publicAPI.bind();
|
|
210
211
|
}; //---------------------------------------------------------------------------
|
|
211
212
|
|
|
212
213
|
|
|
213
214
|
publicAPI.deactivate = function () {
|
|
214
|
-
if (model.
|
|
215
|
-
model.
|
|
215
|
+
if (model._openGLRenderWindow) {
|
|
216
|
+
model._openGLRenderWindow.deactivateTexture(publicAPI);
|
|
216
217
|
}
|
|
217
218
|
}; //---------------------------------------------------------------------------
|
|
218
219
|
|
|
@@ -278,14 +279,14 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
278
279
|
model.context.texParameteri(model.target, model.context.TEXTURE_WRAP_S, publicAPI.getOpenGLWrapMode(model.wrapS));
|
|
279
280
|
model.context.texParameteri(model.target, model.context.TEXTURE_WRAP_T, publicAPI.getOpenGLWrapMode(model.wrapT));
|
|
280
281
|
|
|
281
|
-
if (model.
|
|
282
|
+
if (model._openGLRenderWindow.getWebgl2()) {
|
|
282
283
|
model.context.texParameteri(model.target, model.context.TEXTURE_WRAP_R, publicAPI.getOpenGLWrapMode(model.wrapR));
|
|
283
284
|
}
|
|
284
285
|
|
|
285
286
|
model.context.texParameteri(model.target, model.context.TEXTURE_MIN_FILTER, publicAPI.getOpenGLFilterMode(model.minificationFilter));
|
|
286
287
|
model.context.texParameteri(model.target, model.context.TEXTURE_MAG_FILTER, publicAPI.getOpenGLFilterMode(model.magnificationFilter));
|
|
287
288
|
|
|
288
|
-
if (model.
|
|
289
|
+
if (model._openGLRenderWindow.getWebgl2()) {
|
|
289
290
|
model.context.texParameteri(model.target, model.context.TEXTURE_BASE_LEVEL, model.baseLevel);
|
|
290
291
|
model.context.texParameteri(model.target, model.context.TEXTURE_MAX_LEVEL, model.maxLevel);
|
|
291
292
|
} // model.context.texParameterf(model.target, model.context.TEXTURE_MIN_LOD, model.minLOD);
|
|
@@ -312,14 +313,14 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
312
313
|
publicAPI.getDefaultInternalFormat = function (vtktype, numComps) {
|
|
313
314
|
var result = 0; // try default next
|
|
314
315
|
|
|
315
|
-
result = model.
|
|
316
|
+
result = model._openGLRenderWindow.getDefaultTextureInternalFormat(vtktype, numComps, false);
|
|
316
317
|
|
|
317
318
|
if (result) {
|
|
318
319
|
return result;
|
|
319
320
|
} // try floating point
|
|
320
321
|
|
|
321
322
|
|
|
322
|
-
result = _this.
|
|
323
|
+
result = _this._openGLRenderWindow.getDefaultTextureInternalFormat(vtktype, numComps, true);
|
|
323
324
|
|
|
324
325
|
if (!result) {
|
|
325
326
|
vtkDebugMacro('Unsupported internal texture type!');
|
|
@@ -345,7 +346,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
345
346
|
|
|
346
347
|
|
|
347
348
|
publicAPI.getDefaultFormat = function (vtktype, numComps) {
|
|
348
|
-
if (model.
|
|
349
|
+
if (model._openGLRenderWindow.getWebgl2()) {
|
|
349
350
|
switch (numComps) {
|
|
350
351
|
case 1:
|
|
351
352
|
return model.context.RED;
|
|
@@ -395,7 +396,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
395
396
|
var useHalfFloatType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
396
397
|
|
|
397
398
|
// DON'T DEAL with VTK_CHAR as this is platform dependent.
|
|
398
|
-
if (model.
|
|
399
|
+
if (model._openGLRenderWindow.getWebgl2()) {
|
|
399
400
|
switch (vtkScalarType) {
|
|
400
401
|
// case VtkDataTypes.SIGNED_CHAR:
|
|
401
402
|
// return model.context.BYTE;
|
|
@@ -600,7 +601,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
600
601
|
|
|
601
602
|
|
|
602
603
|
var halfFloatExt = model.context.getExtension('OES_texture_half_float');
|
|
603
|
-
var halfFloat = model.
|
|
604
|
+
var halfFloat = model._openGLRenderWindow.getWebgl2() ? model.openGLDataType === model.context.HALF_FLOAT : halfFloatExt && model.openGLDataType === halfFloatExt.HALF_FLOAT_OES;
|
|
604
605
|
|
|
605
606
|
if (halfFloat) {
|
|
606
607
|
for (var _idx2 = 0; _idx2 < data.length; _idx2++) {
|
|
@@ -630,7 +631,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
630
631
|
|
|
631
632
|
|
|
632
633
|
function scaleTextureToHighestPowerOfTwo(data) {
|
|
633
|
-
if (model.
|
|
634
|
+
if (model._openGLRenderWindow.getWebgl2()) {
|
|
634
635
|
// No need if webGL2
|
|
635
636
|
return data;
|
|
636
637
|
}
|
|
@@ -740,7 +741,9 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
740
741
|
model.height = height;
|
|
741
742
|
model.depth = 1;
|
|
742
743
|
model.numberOfDimensions = 2;
|
|
743
|
-
|
|
744
|
+
|
|
745
|
+
model._openGLRenderWindow.activateTexture(publicAPI);
|
|
746
|
+
|
|
744
747
|
publicAPI.createTexture();
|
|
745
748
|
publicAPI.bind(); // Create an array of texture with one texture
|
|
746
749
|
|
|
@@ -783,7 +786,9 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
783
786
|
model.height = height;
|
|
784
787
|
model.depth = 1;
|
|
785
788
|
model.numberOfDimensions = 2;
|
|
786
|
-
|
|
789
|
+
|
|
790
|
+
model._openGLRenderWindow.activateTexture(publicAPI);
|
|
791
|
+
|
|
787
792
|
model.maxLevel = data.length / 6 - 1;
|
|
788
793
|
publicAPI.createTexture();
|
|
789
794
|
publicAPI.bind();
|
|
@@ -849,7 +854,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
849
854
|
publicAPI.getOpenGLDataType(dataType);
|
|
850
855
|
model.format = model.context.DEPTH_COMPONENT;
|
|
851
856
|
|
|
852
|
-
if (model.
|
|
857
|
+
if (model._openGLRenderWindow.getWebgl2()) {
|
|
853
858
|
if (dataType === VtkDataTypes.FLOAT) {
|
|
854
859
|
model.internalFormat = model.context.DEPTH_COMPONENT32F;
|
|
855
860
|
} else {
|
|
@@ -870,7 +875,9 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
870
875
|
model.height = height;
|
|
871
876
|
model.depth = 1;
|
|
872
877
|
model.numberOfDimensions = 2;
|
|
873
|
-
|
|
878
|
+
|
|
879
|
+
model._openGLRenderWindow.activateTexture(publicAPI);
|
|
880
|
+
|
|
874
881
|
publicAPI.createTexture();
|
|
875
882
|
publicAPI.bind(); // Source texture data from the PBO.
|
|
876
883
|
// model.context.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
|
@@ -904,7 +911,9 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
904
911
|
model.height = image.height;
|
|
905
912
|
model.depth = 1;
|
|
906
913
|
model.numberOfDimensions = 2;
|
|
907
|
-
|
|
914
|
+
|
|
915
|
+
model._openGLRenderWindow.activateTexture(publicAPI);
|
|
916
|
+
|
|
908
917
|
publicAPI.createTexture();
|
|
909
918
|
publicAPI.bind(); // Source texture data from the PBO.
|
|
910
919
|
// model.context.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
|
@@ -994,7 +1003,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
994
1003
|
var useHalfFloatType = true;
|
|
995
1004
|
publicAPI.getOpenGLDataType(dataType, useHalfFloatType);
|
|
996
1005
|
var halfFloatExt = model.context.getExtension('OES_texture_half_float');
|
|
997
|
-
var useHalfFloat = model.
|
|
1006
|
+
var useHalfFloat = model._openGLRenderWindow.getWebgl2() ? model.openGLDataType === model.context.HALF_FLOAT : halfFloatExt && model.openGLDataType === halfFloatExt.HALF_FLOAT_OES;
|
|
998
1007
|
|
|
999
1008
|
if (!useHalfFloat) {
|
|
1000
1009
|
return false;
|
|
@@ -1029,7 +1038,9 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1029
1038
|
model.height = height;
|
|
1030
1039
|
model.depth = depth;
|
|
1031
1040
|
model.numberOfDimensions = 3;
|
|
1032
|
-
|
|
1041
|
+
|
|
1042
|
+
model._openGLRenderWindow.activateTexture(publicAPI);
|
|
1043
|
+
|
|
1033
1044
|
publicAPI.createTexture();
|
|
1034
1045
|
publicAPI.bind(); // Create an array of texture with one texture
|
|
1035
1046
|
|
|
@@ -1086,7 +1097,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1086
1097
|
model.volumeInfo.dataComputedOffset = computedOffset;
|
|
1087
1098
|
var useHalfFloat = checkUseHalfFloat(dataType, computedOffset, computedScale, preferSizeOverAccuracy); // WebGL2 path, we have 3d textures etc
|
|
1088
1099
|
|
|
1089
|
-
if (model.
|
|
1100
|
+
if (model._openGLRenderWindow.getWebgl2()) {
|
|
1090
1101
|
if (dataType === VtkDataTypes.FLOAT || useHalfFloat && (dataType === VtkDataTypes.SHORT || dataType === VtkDataTypes.UNSIGNED_SHORT)) {
|
|
1091
1102
|
return publicAPI.create3DFromRaw(width, height, depth, numComps, dataType, data);
|
|
1092
1103
|
}
|
|
@@ -1199,7 +1210,9 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1199
1210
|
var targetHeight = nearestPowerOfTwo(height * yreps / ystride);
|
|
1200
1211
|
model.width = targetWidth;
|
|
1201
1212
|
model.height = targetHeight;
|
|
1202
|
-
|
|
1213
|
+
|
|
1214
|
+
model._openGLRenderWindow.activateTexture(publicAPI);
|
|
1215
|
+
|
|
1203
1216
|
publicAPI.createTexture();
|
|
1204
1217
|
publicAPI.bind(); // store the information, we will need it later
|
|
1205
1218
|
|
|
@@ -1256,16 +1269,16 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1256
1269
|
};
|
|
1257
1270
|
|
|
1258
1271
|
publicAPI.setOpenGLRenderWindow = function (rw) {
|
|
1259
|
-
if (model.
|
|
1272
|
+
if (model._openGLRenderWindow === rw) {
|
|
1260
1273
|
return;
|
|
1261
1274
|
}
|
|
1262
1275
|
|
|
1263
1276
|
publicAPI.releaseGraphicsResources();
|
|
1264
|
-
model.
|
|
1277
|
+
model._openGLRenderWindow = rw;
|
|
1265
1278
|
model.context = null;
|
|
1266
1279
|
|
|
1267
1280
|
if (rw) {
|
|
1268
|
-
model.context = model.
|
|
1281
|
+
model.context = model._openGLRenderWindow.getContext();
|
|
1269
1282
|
}
|
|
1270
1283
|
}; //----------------------------------------------------------------------------
|
|
1271
1284
|
|
|
@@ -1283,7 +1296,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1283
1296
|
|
|
1284
1297
|
|
|
1285
1298
|
var DEFAULT_VALUES = {
|
|
1286
|
-
|
|
1299
|
+
_openGLRenderWindow: null,
|
|
1287
1300
|
context: null,
|
|
1288
1301
|
handle: 0,
|
|
1289
1302
|
sendParametersTime: null,
|
|
@@ -14,11 +14,11 @@ function vtkOpenGLVertexArrayObject(publicAPI, model) {
|
|
|
14
14
|
publicAPI.initialize = function () {
|
|
15
15
|
model.instancingExtension = null;
|
|
16
16
|
|
|
17
|
-
if (!model.
|
|
17
|
+
if (!model._openGLRenderWindow.getWebgl2()) {
|
|
18
18
|
model.instancingExtension = model.context.getExtension('ANGLE_instanced_arrays');
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
if (!model.forceEmulation && model.
|
|
21
|
+
if (!model.forceEmulation && model._openGLRenderWindow && model._openGLRenderWindow.getWebgl2()) {
|
|
22
22
|
model.extension = null;
|
|
23
23
|
model.supported = true;
|
|
24
24
|
model.handleVAO = model.context.createVertexArray();
|
|
@@ -303,16 +303,16 @@ function vtkOpenGLVertexArrayObject(publicAPI, model) {
|
|
|
303
303
|
};
|
|
304
304
|
|
|
305
305
|
publicAPI.setOpenGLRenderWindow = function (rw) {
|
|
306
|
-
if (model.
|
|
306
|
+
if (model._openGLRenderWindow === rw) {
|
|
307
307
|
return;
|
|
308
308
|
}
|
|
309
309
|
|
|
310
310
|
publicAPI.releaseGraphicsResources();
|
|
311
|
-
model.
|
|
311
|
+
model._openGLRenderWindow = rw;
|
|
312
312
|
model.context = null;
|
|
313
313
|
|
|
314
314
|
if (rw) {
|
|
315
|
-
model.context = model.
|
|
315
|
+
model.context = model._openGLRenderWindow.getContext();
|
|
316
316
|
}
|
|
317
317
|
};
|
|
318
318
|
} // ----------------------------------------------------------------------------
|
|
@@ -326,8 +326,8 @@ var DEFAULT_VALUES = {
|
|
|
326
326
|
handleProgram: 0,
|
|
327
327
|
supported: true,
|
|
328
328
|
buffers: null,
|
|
329
|
-
context: null,
|
|
330
|
-
|
|
329
|
+
context: null // _openGLRenderWindow: null,
|
|
330
|
+
|
|
331
331
|
}; // ----------------------------------------------------------------------------
|
|
332
332
|
|
|
333
333
|
function extend(publicAPI, model) {
|
|
@@ -16,9 +16,9 @@ function vtkOpenGLVolume(publicAPI, model) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
if (prepass) {
|
|
19
|
-
model.
|
|
19
|
+
model._openGLRenderWindow = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderWindow');
|
|
20
20
|
model.openGLRenderer = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderer');
|
|
21
|
-
model.context = model.
|
|
21
|
+
model.context = model._openGLRenderWindow.getContext();
|
|
22
22
|
publicAPI.prepareNodes();
|
|
23
23
|
publicAPI.addMissingNode(model.renderable.getMapper());
|
|
24
24
|
publicAPI.removeUnusedNodes();
|
|
@@ -85,6 +85,7 @@ var DEFAULT_VALUES = {// context: null,
|
|
|
85
85
|
// keyMatrixTime: null,
|
|
86
86
|
// normalMatrix: null,
|
|
87
87
|
// MCWCMatrix: null,
|
|
88
|
+
// _openGLRenderWindow: null,
|
|
88
89
|
}; // ----------------------------------------------------------------------------
|
|
89
90
|
|
|
90
91
|
function extend(publicAPI, model) {
|
|
@@ -64,15 +64,15 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
64
64
|
|
|
65
65
|
publicAPI.volumePass = function (prepass, renderPass) {
|
|
66
66
|
if (prepass) {
|
|
67
|
-
model.
|
|
68
|
-
model.context = model.
|
|
69
|
-
model.tris.setOpenGLRenderWindow(model.
|
|
70
|
-
model.jitterTexture.setOpenGLRenderWindow(model.
|
|
71
|
-
model.framebuffer.setOpenGLRenderWindow(model.
|
|
72
|
-
|
|
73
|
-
model.scalarTexture.setOpenGLRenderWindow(model.
|
|
74
|
-
model.colorTexture.setOpenGLRenderWindow(model.
|
|
75
|
-
model.opacityTexture.setOpenGLRenderWindow(model.
|
|
67
|
+
model._openGLRenderWindow = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderWindow');
|
|
68
|
+
model.context = model._openGLRenderWindow.getContext();
|
|
69
|
+
model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
70
|
+
model.jitterTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
71
|
+
model.framebuffer.setOpenGLRenderWindow(model._openGLRenderWindow); // Per Component?
|
|
72
|
+
|
|
73
|
+
model.scalarTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
74
|
+
model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
75
|
+
model.opacityTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
76
76
|
model.openGLVolume = publicAPI.getFirstAncestorOfType('vtkOpenGLVolume');
|
|
77
77
|
var actor = model.openGLVolume.getRenderable();
|
|
78
78
|
model.openGLRenderer = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderer');
|
|
@@ -134,7 +134,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
134
134
|
// a system will execute every step regardless
|
|
135
135
|
|
|
136
136
|
|
|
137
|
-
var ext = model.currentInput.
|
|
137
|
+
var ext = model.currentInput.getSpatialExtent();
|
|
138
138
|
var spc = model.currentInput.getSpacing();
|
|
139
139
|
var vsize = new Float64Array(3);
|
|
140
140
|
vec3.set(vsize, (ext[1] - ext[0]) * spc[0], (ext[3] - ext[2]) * spc[1], (ext[5] - ext[4]) * spc[2]);
|
|
@@ -269,7 +269,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
var ext = model.currentInput.
|
|
272
|
+
var ext = model.currentInput.getSpatialExtent();
|
|
273
273
|
var spc = model.currentInput.getSpacing();
|
|
274
274
|
var vsize = new Float64Array(3);
|
|
275
275
|
vec3.set(vsize, (ext[1] - ext[0]) * spc[0], (ext[3] - ext[2]) * spc[1], (ext[5] - ext[4]) * spc[2]);
|
|
@@ -312,7 +312,8 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
312
312
|
};
|
|
313
313
|
publicAPI.buildShaders(shaders, ren, actor); // compile and bind the program if needed
|
|
314
314
|
|
|
315
|
-
var newShader = model.
|
|
315
|
+
var newShader = model._openGLRenderWindow.getShaderCache().readyShaderProgramArray(shaders.Vertex, shaders.Fragment, shaders.Geometry); // if the shader changed reinitialize the VAO
|
|
316
|
+
|
|
316
317
|
|
|
317
318
|
if (newShader !== cellBO.getProgram()) {
|
|
318
319
|
cellBO.setProgram(newShader); // reset the VAO as the shader has changed
|
|
@@ -322,7 +323,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
322
323
|
|
|
323
324
|
cellBO.getShaderSourceTime().modified();
|
|
324
325
|
} else {
|
|
325
|
-
model.
|
|
326
|
+
model._openGLRenderWindow.getShaderCache().readyShaderProgram(cellBO.getProgram());
|
|
326
327
|
}
|
|
327
328
|
|
|
328
329
|
cellBO.getVAO().bind();
|
|
@@ -428,10 +429,10 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
428
429
|
program.setUniformi('cameraParallel', cam.getParallelProjection());
|
|
429
430
|
}
|
|
430
431
|
|
|
431
|
-
var ext = model.currentInput.
|
|
432
|
+
var ext = model.currentInput.getSpatialExtent();
|
|
432
433
|
var spc = model.currentInput.getSpacing();
|
|
433
434
|
var vsize = new Float64Array(3);
|
|
434
|
-
vec3.set(vsize, (ext[1] - ext[0]
|
|
435
|
+
vec3.set(vsize, (ext[1] - ext[0]) * spc[0], (ext[3] - ext[2]) * spc[1], (ext[5] - ext[4]) * spc[2]);
|
|
435
436
|
program.setUniform3f('vSpacing', spc[0], spc[1], spc[2]);
|
|
436
437
|
vec3.set(pos, ext[0], ext[2], ext[4]);
|
|
437
438
|
model.currentInput.indexToWorldVec3(pos, pos);
|
|
@@ -454,7 +455,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
454
455
|
program.setUniform3f('vVCToIJK', vctoijk[0], vctoijk[1], vctoijk[2]);
|
|
455
456
|
program.setUniform3i('volumeDimensions', dims[0], dims[1], dims[2]);
|
|
456
457
|
|
|
457
|
-
if (!model.
|
|
458
|
+
if (!model._openGLRenderWindow.getWebgl2()) {
|
|
458
459
|
var volInfo = model.scalarTexture.getVolumeInfo();
|
|
459
460
|
program.setUniformf('texWidth', model.scalarTexture.getWidth());
|
|
460
461
|
program.setUniformf('texHeight', model.scalarTexture.getHeight());
|
|
@@ -739,7 +740,8 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
739
740
|
model._lastScale = model.renderable.getImageSampleDistance() * model.renderable.getImageSampleDistance();
|
|
740
741
|
}
|
|
741
742
|
|
|
742
|
-
var size = model.
|
|
743
|
+
var size = model._openGLRenderWindow.getFramebufferSize();
|
|
744
|
+
|
|
743
745
|
model._smallViewportWidth = Math.ceil(size[0] / Math.sqrt(model._lastScale));
|
|
744
746
|
model._smallViewportHeight = Math.ceil(size[1] / Math.sqrt(model._lastScale));
|
|
745
747
|
});
|
|
@@ -747,7 +749,8 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
747
749
|
|
|
748
750
|
|
|
749
751
|
if (model._useSmallViewport) {
|
|
750
|
-
var size = model.
|
|
752
|
+
var size = model._openGLRenderWindow.getFramebufferSize(); // adjust viewportSize to always be at most the dest fo size
|
|
753
|
+
|
|
751
754
|
|
|
752
755
|
if (model._smallViewportHeight > size[1]) {
|
|
753
756
|
model._smallViewportHeight = size[1];
|
|
@@ -834,20 +837,21 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
834
837
|
model.framebuffer.restorePreviousBindingsAndBuffers();
|
|
835
838
|
|
|
836
839
|
if (model.copyShader === null) {
|
|
837
|
-
model.copyShader = model.
|
|
840
|
+
model.copyShader = model._openGLRenderWindow.getShaderCache().readyShaderProgramArray(['//VTK::System::Dec', 'attribute vec4 vertexDC;', 'uniform vec2 tfactor;', 'varying vec2 tcoord;', 'void main() { tcoord = vec2(vertexDC.x*0.5 + 0.5, vertexDC.y*0.5 + 0.5) * tfactor; gl_Position = vertexDC; }'].join('\n'), ['//VTK::System::Dec', '//VTK::Output::Dec', 'uniform sampler2D texture1;', 'varying vec2 tcoord;', 'void main() { gl_FragData[0] = texture2D(texture1,tcoord); }'].join('\n'), '');
|
|
838
841
|
var program = model.copyShader;
|
|
839
842
|
model.copyVAO = vtkVertexArrayObject.newInstance();
|
|
840
|
-
model.copyVAO.setOpenGLRenderWindow(model.
|
|
843
|
+
model.copyVAO.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
841
844
|
model.tris.getCABO().bind();
|
|
842
845
|
|
|
843
846
|
if (!model.copyVAO.addAttributeArray(program, model.tris.getCABO(), 'vertexDC', model.tris.getCABO().getVertexOffset(), model.tris.getCABO().getStride(), model.context.FLOAT, 3, model.context.FALSE)) {
|
|
844
847
|
vtkErrorMacro('Error setting vertexDC in copy shader VAO.');
|
|
845
848
|
}
|
|
846
849
|
} else {
|
|
847
|
-
model.
|
|
850
|
+
model._openGLRenderWindow.getShaderCache().readyShaderProgram(model.copyShader);
|
|
848
851
|
}
|
|
849
852
|
|
|
850
|
-
var size = model.
|
|
853
|
+
var size = model._openGLRenderWindow.getFramebufferSize();
|
|
854
|
+
|
|
851
855
|
model.context.viewport(0, 0, size[0], size[1]); // activate texture
|
|
852
856
|
|
|
853
857
|
var tex = model.framebuffer.getColorTexture();
|
|
@@ -959,14 +963,14 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
959
963
|
}
|
|
960
964
|
}
|
|
961
965
|
|
|
962
|
-
model.opacityTexture.releaseGraphicsResources(model.
|
|
966
|
+
model.opacityTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
963
967
|
model.opacityTexture.setMinificationFilter(Filter.LINEAR);
|
|
964
968
|
model.opacityTexture.setMagnificationFilter(Filter.LINEAR); // use float texture where possible because we really need the resolution
|
|
965
969
|
// for this table. Errors in low values of opacity accumulate to
|
|
966
970
|
// visible artifacts. High values of opacity quickly terminate without
|
|
967
971
|
// artifacts.
|
|
968
972
|
|
|
969
|
-
if (model.
|
|
973
|
+
if (model._openGLRenderWindow.getWebgl2() || model.context.getExtension('OES_texture_float') && model.context.getExtension('OES_texture_float_linear')) {
|
|
970
974
|
model.opacityTexture.create2DFromRaw(oWidth, 2 * numIComps, 1, VtkDataTypes.FLOAT, ofTable);
|
|
971
975
|
} else {
|
|
972
976
|
var _oTable = new Uint8Array(oSize);
|
|
@@ -1002,7 +1006,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
1002
1006
|
}
|
|
1003
1007
|
}
|
|
1004
1008
|
|
|
1005
|
-
model.colorTexture.releaseGraphicsResources(model.
|
|
1009
|
+
model.colorTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
1006
1010
|
model.colorTexture.setMinificationFilter(Filter.LINEAR);
|
|
1007
1011
|
model.colorTexture.setMagnificationFilter(Filter.LINEAR);
|
|
1008
1012
|
model.colorTexture.create2DFromRaw(cWidth, 2 * numIComps, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
@@ -1015,7 +1019,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
1015
1019
|
if (model.scalarTextureString !== toString) {
|
|
1016
1020
|
// Build the textures
|
|
1017
1021
|
var dims = image.getDimensions();
|
|
1018
|
-
model.scalarTexture.releaseGraphicsResources(model.
|
|
1022
|
+
model.scalarTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
1019
1023
|
model.scalarTexture.resetFormatAndType();
|
|
1020
1024
|
model.scalarTexture.create3DFilterableFromRaw(dims[0], dims[1], dims[2], numComp, scalars.getDataType(), scalars.getData(), model.renderable.getPreferSizeOverAccuracy());
|
|
1021
1025
|
model.scalarTextureString = toString;
|
|
@@ -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 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";
|
|
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 vec3 index = (vWCtoIDX * vertex).xyz;\n\n // half voxel fix for labelmapOutline \n return (index + vec3(0.5)) / 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;\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 };
|