Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Ying-Qiu Zheng
fsleyes
Commits
50edd483
Commit
50edd483
authored
Feb 19, 2021
by
Paul McCarthy
🚵
Browse files
Merge branch 'enh/volume-lighting' into 'master'
Enh/volume lighting See merge request fsl/fsleyes/fsleyes!222
parents
8697a284
7c23a6af
Changes
202
Hide whitespace changes
Inline
Side-by-side
.ci/test_template.sh
View file @
50edd483
...
...
@@ -3,13 +3,14 @@
set
-e
apt-get
install
-y
bc
# Temporary: this should be done
# in docker image definition
# in docker image definition
s
apt
install
-y
locales
locale-gen en_US.UTF-8
locale-gen en_GB.UTF-8
update-locale
export
LANG
=
en_GB.UTF-8
# If running on a fork repository, we merge in the
# upstream/master branch. This is done so that merge
...
...
@@ -72,27 +73,29 @@ if [ "$TEST_STYLE"x != "x" ]; then flake8 fsleyes || t
if
[
"
$TEST_STYLE
"
x
!=
"x"
]
;
then
pylint
--output-format
=
colorized fsleyes
||
true
;
fi
;
if
[
"
$TEST_STYLE
"
x
!=
"x"
]
;
then
exit
0
;
fi
# Run the tests
export
MPLBACKEND
=
wxagg
# Run the tests
. First batch requires
# a GUI, so we run via xvfb-run
export
FSLEYES_TEST_GL
=
2.1
((
xvfb-run
-a
-s
"-screen 0 1920x1200x24"
pytest
--cov-report
=
--cov-append
-m
"not (clitest or overlayclitest)"
&&
echo
"0"
>
status
)
||
echo
"1"
>
status
)
||
true
status
=
`
cat
status
`
failed
=
$status
sleep
5
((
xvfb-run
-a
-s
"-screen 0 1920x1200x24"
pytest
--cov-report
=
--cov-append
-m
"clitest"
&&
echo
"0"
>
status
)
||
echo
"1"
>
status
)
||
true
# Remaining tests are all off-screen,
# so we can use osmesa
((
pytest
--cov-report
=
--cov-append
-m
"clitest"
&&
echo
"0"
>
status
)
||
echo
"1"
>
status
)
||
true
status
=
`
cat
status
`
failed
=
`
echo
"
$status
+
$failed
"
| bc
`
sleep
5
((
xvfb-run
-a
-s
"-screen 0 1920x1200x24"
pytest
--cov-report
=
--cov-append
-m
"overlayclitest"
&&
echo
"0"
>
status
)
||
echo
"1"
>
status
)
||
true
((
pytest
--cov-report
=
--cov-append
-m
"overlayclitest"
&&
echo
"0"
>
status
)
||
echo
"1"
>
status
)
||
true
status
=
`
cat
status
`
failed
=
`
echo
"
$status
+
$failed
"
| bc
`
sleep
5
# test overlay types for GL14 as well
export
FSLEYES_TEST_GL
=
1.4
((
xvfb-run
-a
-s
"-screen 0 1920x1200x24"
pytest
--cov-report
=
--cov-append
-m
"overlayclitest"
&&
echo
"0"
>
status
)
||
echo
"1"
>
status
)
||
true
((
pytest
--cov-report
=
--cov-append
-m
"overlayclitest"
&&
echo
"0"
>
status
)
||
echo
"1"
>
status
)
||
true
status
=
`
cat
status
`
failed
=
`
echo
"
$status
+
$failed
"
| bc
`
...
...
.docker/fsleyes-py37-wxpy4-gtk3/Dockerfile
View file @
50edd483
...
...
@@ -6,7 +6,7 @@ ENV PY_PACKAGES "python3-pip python3.7-venv"
ENV
PY_VENV "python3.7 -m venv"
ENV
WXPYTHON_VERSION "wxPython-4.1.1"
ENV
DEBIAN_FRONTEND "noninteractive"
ENV
LANG "
C
.UTF-8"
ENV
LANG "
en_GB
.UTF-8"
ADD
scripts/install_system_deps.sh /scripts/install_system_deps.sh
ADD
scripts/install_python.sh /scripts/install_python.sh
...
...
.docker/fsleyes-py38-wxpy4-gtk3/Dockerfile
View file @
50edd483
...
...
@@ -6,7 +6,7 @@ ENV PY_PACKAGES "python3-pip python3.8-venv"
ENV
PY_VENV "python3.8 -m venv"
ENV
WXPYTHON_VERSION "wxPython-4.1.1"
ENV
DEBIAN_FRONTEND "noninteractive"
ENV
LANG "
C
.UTF-8"
ENV
LANG "
en_GB
.UTF-8"
ADD
scripts/install_system_deps.sh /scripts/install_system_deps.sh
ADD
scripts/install_python.sh /scripts/install_python.sh
...
...
.docker/fsleyes-py39-wxpy4-gtk3/Dockerfile
View file @
50edd483
...
...
@@ -6,7 +6,7 @@ ENV PY_PACKAGES "python3-pip python3.9-venv"
ENV
PY_VENV "python3.9 -m venv"
ENV
WXPYTHON_VERSION "wxPython-4.1.1"
ENV
DEBIAN_FRONTEND "noninteractive"
ENV
LANG "
C
.UTF-8"
ENV
LANG "
en_GB
.UTF-8"
ADD
scripts/install_system_deps.sh /scripts/install_system_deps.sh
ADD
scripts/install_python.sh /scripts/install_python.sh
...
...
.docker/scripts/install_system_deps.sh
View file @
50edd483
...
...
@@ -21,6 +21,11 @@ apt-get install -y --ignore-missing \
libhdf5-dev
\
openssh-client
apt
install
-y
locales
locale-gen en_US.UTF-8
locale-gen en_GB.UTF-8
update-locale
cat
/etc/lsb-release |
grep
"14.04"
&&
apt-get
install
-y
libspatialindex-c3
||
true
cat
/etc/lsb-release |
grep
"16.04"
&&
apt-get
install
-y
libspatialindex-c4v5
||
true
cat
/etc/lsb-release |
grep
"18.04"
&&
apt-get
install
-y
libspatialindex-c4v5
||
true
...
...
.gitlab-ci.yml
View file @
50edd483
...
...
@@ -208,6 +208,12 @@ test:3.8:
<<
:
*test_template
test:3.9:
stage
:
test
image
:
pauldmccarthy/fsleyes-py39-wxpy4-gtk3
<<
:
*test_template
test:build-pypi-dist:
stage
:
test
image
:
pauldmccarthy/fsleyes-py36-wxpy4-gtk3
...
...
CHANGELOG.rst
View file @
50edd483
...
...
@@ -13,6 +13,18 @@ chronological order.
--------------------------
Added
^^^^^
* The lighting effect in the 3D view is now applied to ``volume`` overlays
(OpenGL 2.1 or newer only).
* New ``--lightDistance`` option (for 3D view), allowing the distance of
the light source from the centre of the display bounding box to be set.
* New ``--noBlendByIntensity`` option, for ``volume`` overlays in the 3D view,
allowing the modulation of samples by voxel intensity to be disabled.
Changed
^^^^^^^
...
...
@@ -22,12 +34,21 @@ Changed
* Removed dependence on [Free]GLUT - this means that ``fsleyes render`` can
now be used on headless systems without using ``xvfb-run``, as long as
`OSMesa <https://docs.mesa3d.org/osmesa.html>`_ is installed.
* The ``--lightPos`` command-line option (for the 3D view) has been changed to
expect three rotation values (in degrees), which specify the position of the
light source with respect to the centre of the display bounding box. This
can be combined with the new ``--lightDistance`` option to specify the
position of the light source.
* FSLeyes no longer ignores the ``LIBGL_ALWAYS_INDIRECT`` environment
variable.
Fixed
^^^^^
* Various fixes and improvements to the lighting effect on ``mesh`` overlays
in the 3D view.
* When opening a ``melodic_IC.nii.gz`` file with the
``--autoDisplay'`/``-ad``, option, the ``melodic_IC`` file is now selected
by default, instead of the ``mean`` underlay.
...
...
assets/gl/gl14/glmesh_3d_data_frag.prog
View file @
50edd483
...
...
@@ -12,11 +12,10 @@
# {{ param_modulate }}
# {{ param_flatColour }}
# {{ param4_cmapXform }}
#
# {{ param_lighting }} - The xyz components contain the light position
# in display coordinates. The w component contains a
# 1 if lighting should be applied, or a -1 if
# lighting should not be applied.
# {{ param_lighting }} - The xyz components contain the light position
# in display coordinates. The w component contains
# a 1 if lighting should be applied, or a -1 if
# lighting should not be applied.
#
# Input textures:
# - {{ texture_cmap }}
...
...
@@ -27,7 +26,6 @@
# - {{ varying_modulateData }} - Vertex alpha modulation value
# - {{ varying_vertex }} - Vertex position in display coordinates
# - {{ varying_normal }} - Vertex normal
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
...
...
assets/gl/gl14/glmesh_3d_data_vert.prog
View file @
50edd483
...
...
@@ -5,7 +5,7 @@
#
# Input parameters:
#
# {{ param
4
_normalMatrix }} - Matrix to transform normal vectors into
# {{ param
3
_normalMatrix }} - Matrix to transform normal vectors into
# display coordinates.
#
# Input attributes:
...
...
@@ -15,13 +15,15 @@
# Outputs:
# {{ varying_vertexData }} - As above, passed through to fragment shader.
# {{ varying_modulateData }} - As above, passed through to fragment shader.
# {{ varying_vertex }} - The vertex position in
display
coordinates.
# {{ varying_vertex }} - The vertex position in
view
coordinates.
# {{ varying_normal }} - As above, passed through to fragment shader.
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
PARAM normalMatrix[4] = {{ param4_normalMatrix }};
PARAM normalMatrix[3] = {{ param3_normalMatrix }};
TEMP normal;
# Transform the vertex position into clip coordinates
DP4 result.position.x, state.matrix.mvp.row[0], vertex.position;
...
...
@@ -36,10 +38,17 @@ DP4 {{ varying_vertex }}.z, state.matrix.modelview[0].row[2], vertex.position;
DP4 {{ varying_vertex }}.w, state.matrix.modelview[0].row[3], vertex.position;
# Transform the normal vector
DP4 {{ varying_normal }}.x, normalMatrix[0], {{ attr_normal }};
DP4 {{ varying_normal }}.y, normalMatrix[1], {{ attr_normal }};
DP4 {{ varying_normal }}.z, normalMatrix[2], {{ attr_normal }};
DP4 {{ varying_normal }}.w, normalMatrix[3], {{ attr_normal }};
DP3 normal.x, normalMatrix[0], {{ attr_normal }};
DP3 normal.y, normalMatrix[1], {{ attr_normal }};
DP3 normal.z, normalMatrix[2], {{ attr_normal }};
# Normalise to unit length
DP3 normal.w, normal, normal;
RSQ normal.w, normal.w;
MUL normal, normal, normal.w;
MOV normal.w, 0;
MOV {{ varying_normal }}, normal;
# Copy the vertex/modulate data
MOV {{ varying_vertexData }}, {{ attr_vertexData }};
...
...
assets/gl/gl14/glmesh_3d_flat_frag.prog
View file @
50edd483
...
...
@@ -5,16 +5,15 @@
# Input parameters:
#
# {{ param_colour }} - The mesh colour
#
# {{ param_lighting }} - The xyz components contain the light position
# in display coordinates. The w component contains
a
# 1 if lighting should be applied, or a -1 if
# in display coordinates. The w component contains
#
a
1 if lighting should be applied, or a -1 if
# lighting should not be applied.
#
#
# Input varyings:
# - {{ varying_vertex }} - Vertex position in display coordinates
# - {{ varying_normal }} - Vertex normal
# - {{ varying_vertex }}
- Vertex position in display coordinates
# - {{ varying_normal }}
- Vertex normal
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
...
...
assets/gl/gl14/glmesh_3d_flat_vert.prog
View file @
50edd483
...
...
@@ -5,7 +5,7 @@
#
# Input parameters:
#
# {{ param
4
_normalMatrix }} - Matrix to transform normal vectors into
# {{ param
3
_normalMatrix }} - Matrix to transform normal vectors into
# display coordinates.
#
# Input attributes:
...
...
@@ -18,7 +18,9 @@
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
PARAM normalMatrix[4] = {{ param4_normalMatrix }};
PARAM normalMatrix[3] = {{ param3_normalMatrix }};
TEMP normal;
# Transform the vertex position into clip coordinates
DP4 result.position.x, state.matrix.mvp.row[0], vertex.position;
...
...
@@ -33,9 +35,16 @@ DP4 {{ varying_vertex }}.z, state.matrix.modelview[0].row[2], vertex.position;
DP4 {{ varying_vertex }}.w, state.matrix.modelview[0].row[3], vertex.position;
# Transform the normal vector
DP4 {{ varying_normal }}.x, normalMatrix[0], {{ attr_normal }};
DP4 {{ varying_normal }}.y, normalMatrix[1], {{ attr_normal }};
DP4 {{ varying_normal }}.z, normalMatrix[2], {{ attr_normal }};
DP4 {{ varying_normal }}.w, normalMatrix[3], {{ attr_normal }};
DP3 normal.x, normalMatrix[0], {{ attr_normal }};
DP3 normal.y, normalMatrix[1], {{ attr_normal }};
DP3 normal.z, normalMatrix[2], {{ attr_normal }};
# Normalise to unit length
DP3 normal.w, normal, normal;
RSQ normal.w, normal.w;
MUL normal, normal, normal.w;
MOV normal.w, 0;
MOV {{ varying_normal }}, normal;
END
assets/gl/gl14/glmesh_3d_lighting.prog
View file @
50edd483
...
...
@@ -21,21 +21,29 @@ TEMP specular;
# Calculate the direction towards the
# light and normalise it to unit length
#
# lightDir = normalize(lightPos - vertex);
#
SUB lightDir.xyz, {{ lightPos }}, {{ vertex }};
DP3 lightDir.w, lightDir, lightDir;
RSQ lightDir.w, lightDir.w;
MUL lightDir.xyz, lightDir, lightDir.w;
# Normalised camera direction
#
# viewDir = normalize(-vertex)
#
MUL viewDir, {{ vertex }}, -1;
DP3 viewDir.w, viewDir, viewDir;
RSQ viewDir.w, viewDir.w;
MUL viewDir.xyz, viewDir, viewDir.w;
# Normalised reflection angle from
# the light off the surface
#
# reflect(I, N) = I – 2 * dot(N, I) * N
# angle = normalize(reflect(lightDir, normal));
#
DP3 angle.xyz, lightDir, {{ normal }};
MUL angle.xyz, angle, {{ normal }};
MUL angle.xyz, angle, 2;
...
...
@@ -48,9 +56,15 @@ MUL angle.xyz, angle, angle.w;
MOV ambient.x, 0.5;
# Diffuse component, clamped to [0, 1]
#
# diffuse = clamp(dot(normal, lightDir), 0.0, 1.0);
#
DP3_SAT diffuse.x, {{ normal }}, lightDir;
# Specular component, clamped to [0, 1]
#
# spec = clamp(pow(max(dot(angle, viewDir), 0.0), 64), 0.0, 1.0);
#
DP3 specular.x, angle, viewDir;
MAX specular.x, specular.x, 0.0;
...
...
@@ -61,6 +75,9 @@ MOV specular.y, 64.0;
POW_SAT specular.x, specular.x, specular.y;
# Combine the final colour
#
# result = colour * vec3(amb + diff + spec);
#
ADD {{ out_colour }}.rgb, ambient.x, diffuse.x;
ADD {{ out_colour }}.rgb, {{ out_colour }}, specular.x;
MUL {{ out_colour }}.rgb, {{ out_colour }}, {{ colour }};
...
...
assets/gl/gl14/glvolume_3d_frag.prog
View file @
50edd483
...
...
@@ -15,7 +15,9 @@ OPTION ARB_precision_hint_nicest;
# {{ param_negCmap }}
#
# {{ param_screenSize }} - First two components contain the screen width
# and height in pixels.
# and height in pixels. Third component determines whether to modulate
# samples by voxel intensity (blendByIntensity, +1), or whether to
# only use the blend factor (-1).
#
# {{ param_rayStep }} - xyz is a vector defining how far to move through
# the volume texture space on each ray-casting iteration.
...
...
@@ -213,18 +215,33 @@ MAD tempVar.x, tempVar.x, 2.0, -1;
MIN skipTest.x, skipTest.x, tempVar.x;
# Adjust the sample opacity - it is
# a function of the (normalised)
# voxel intensity and the blend factor.
# Adjust the sample opacity -
# if blendByIntesnity (screenSize.z),
# it is a function of the (normalised)
# voxel intensity and the blend factor
# (stored in tempVar.y):
#
# a = 1 - pow(1 - clamp(voxValue, 0, 1), 1 - blendFactor);
#
# Otherwise it is just a function of
# the blend factor (stored in tempVar.x):
#
# a = 1 - blendFactor;
SUB tempVar.x, 1, {{ param_settings }}.x;
# Clamp voxValue to [0, 1]
# (MOV_SAT does not work for me)
MIN colour.a, voxValue.x, 1;
MAX colour.a, colour.a, 0;
MIN tempVar.y, voxValue.x, 1;
MAX tempVar.y, tempVar.y, 0;
SUB tempVar.y, 1, tempVar.y;
SUB tempVar.z, 1, {{ param_settings }}.x;
POW tempVar.y, tempVar.y, tempVar.z;
SUB tempVar.y, 1, tempVar.y;
# blend by intensity or just blend by blend factor
CMP colour.a, {{ param_screenSize }}.z, tempVar.x, tempVar.y;
SUB colour.a, 1, colour.a;
POW colour.a, colour.a, {{ param_settings }}.x;
SUB colour.a, 1, colour.a;
MUL colour.rgb, colour, colour.a;
# Blend the sample into the
...
...
assets/gl/gl21/glmesh_3d_data_frag.glsl
View file @
50edd483
...
...
@@ -6,10 +6,11 @@
#version 120
#pragma include glmesh_data_common.glsl
#pragma include
glmesh_3d
_lighting.glsl
#pragma include
phong
_lighting.glsl
uniform
bool
lighting
;
uniform
vec3
lightPos
;
varying
vec3
fragVertex
;
varying
vec3
fragNormal
;
...
...
@@ -19,8 +20,10 @@ void main(void) {
vec4
colour
=
glmesh_data_colour
();
if
(
lighting
)
{
colour
.
rgb
=
mesh_lighting
(
fragVertex
,
fragNormal
,
lightPos
,
colour
.
rgb
);
colour
.
rgb
=
phong_lighting
(
fragVertex
,
fragNormal
,
lightPos
,
colour
.
rgb
);
}
gl_FragColor
=
colour
;
...
...
assets/gl/gl21/glmesh_3d_flat_frag.glsl
View file @
50edd483
...
...
@@ -4,23 +4,18 @@
* Author: Paul McCarthy <pauldmccarthy@gmail.com>
*/
#version 120
#pragma include
glmesh_3d
_lighting.glsl
#pragma include
phong
_lighting.glsl
/* Colour to use. */
uniform
vec4
colour
;
/* Toggle lighting */
uniform
bool
lighting
;
/* Toggle lighting */
uniform
vec3
lightPos
;
/* Vertex */
varying
vec3
fragVertex
;
/* Vertex normal */
varying
vec3
fragNormal
;
...
...
@@ -30,11 +25,10 @@ void main(void) {
vec4
finalColour
=
colour
;
if
(
lighting
)
{
finalColour
.
rgb
=
mesh_lighting
(
fragVertex
,
fragNormal
,
lightPos
,
finalColour
.
rgb
);
finalColour
.
rgb
=
phong_lighting
(
fragVertex
,
fragNormal
,
lightPos
,
finalColour
.
rgb
);
}
gl_FragColor
=
finalColour
;
...
...
assets/gl/gl21/glmesh_3d_flat_vert.glsl
View file @
50edd483
...
...
@@ -5,14 +5,13 @@
*/
#version 120
attribute
vec3
vertex
;
attribute
vec3
normal
;
varying
vec3
fragVertex
;
varying
vec3
fragNormal
;
attribute
vec3
vertex
;
attribute
vec3
normal
;
varying
vec3
fragVertex
;
varying
vec3
fragNormal
;
void
main
(
void
)
{
fragVertex
=
(
gl_ModelViewMatrix
*
vec4
(
vertex
,
1
)).
xyz
;
fragNormal
=
normalize
(
gl_NormalMatrix
*
normal
);
gl_Position
=
gl_ModelViewProjectionMatrix
*
vec4
(
vertex
,
1
);
fragVertex
=
(
gl_ModelViewMatrix
*
vec4
(
vertex
,
1
)).
xyz
;
fragNormal
=
normalize
(
gl_NormalMatrix
*
normal
);
gl_Position
=
gl_ModelViewProjectionMatrix
*
vec4
(
vertex
,
1
);
}
assets/gl/gl21/glvolume_3d_frag.glsl
View file @
50edd483
...
...
@@ -7,6 +7,7 @@
#pragma include spline_interp.glsl
#pragma include test_in_bounds.glsl
#pragma include phong_lighting.glsl
#pragma include rand.glsl
/*
...
...
@@ -33,14 +34,11 @@ uniform float modOffset;
/*
* Texture containing the colour map.
* Texture containing the colour map
s
.
*/
uniform
sampler1D
colourTexture
;
/*
* Texture containing the negative colour map.
*/
uniform
sampler1D
negColourTexture
;
uniform
bool
useNegCmap
;
/*
* Matrix which can be used to transform a texture value
...
...
@@ -60,28 +58,20 @@ uniform vec3 imageShape;
*/
uniform
vec3
texShape
;
/*
* Flag which determines whether to
* use the negative colour map.
*/
uniform
bool
useNegCmap
;
/*
* Use spline interpolation?
*/
uniform
bool
useSpline
;
/*
* Clip voxels below this value. This must be specified
* in the image texture data range.
* Clip voxels below/above these value. This must be specified
* in the image texture data range. invertClip inverts the logic,
* i.e. clip voxels that are inside the clipLow/High bounds.
*/
uniform
float
clipLow
;
/*
* Clip voxels above this value. This must be specified
* in the image texture data range.
*/
uniform
float
clipHigh
;
uniform
bool
invertClip
;
/*
* Value in the image texture data range which corresponds
...
...
@@ -92,31 +82,11 @@ uniform float clipHigh;
uniform
float
texZero
;
/*
* Invert clipping behaviour - clip voxels
* that are inside the clipLow/High bounds.
*/
uniform
bool
invertClip
;
/*
* Number of active clip planes. Regions which are clipped
* by *all* active clip planes are not drawn.
*/
uniform
int
numClipPlanes
;
/*
* The clip planes, specified as plane equations in the image
* texture coordinate system.
* Clipping planes - see the is_clipped function below.
*/
uniform
int
numClipPlanes
;
uniform
vec4
clipPlanes
[
5
];
/*
* How the clipping planes are applied:
* - 1 clips the intersection of all planes
* - 2 clips the union of all planes
* - 3 clips the complement of all planes
*/
uniform
int
clipMode
;
uniform
int
clipMode
;
/*
* A vector which defines how far to move in one iteration
...
...
@@ -145,6 +115,15 @@ uniform float stepLength;
uniform
float
blendFactor
;
/*
* If true, colours from samples along the ray are modulated
* according to the voxel intensity before being blended.
* Otherwise colours are simply blended according to the
* blendFactor.
*/
uniform
bool
blendByIntensity
;
/*
* Final transparency that the fragment should have.
*/
...
...
@@ -158,23 +137,215 @@ uniform float alpha;
*/
uniform
mat4
tex2ScreenXform
;
/*
* Apply a simple lighting model to the rendered volume.
* Light position is specified in *image texture*
* coordinates.
*/
uniform
bool
lighting
;
uniform
vec3
lightPos
;
/*
*
Corresponding i
mage texture coordinates.
*
I
mage texture coordinates.
*/
varying
vec3
fragTexCoord
;
/*
* Fragment location in display coordinate system.
*/
varying
vec3
fragVertex
;
#pragma include glvolume_common.glsl
/*
* Test the given texture coordinate to see if it is within a
* region clipped by the clipping plane(s).
*
* - numClipPlanes: Number of active clip planes. Regions which are
* clipped by *all* active clip planes are not drawn.
*
* - clipPlanes[5]: The clip planes, specified as plane equations in the
* image texture coordinate system.
*
* - clipMode: How the clipping planes are applied:
* - 1 clips the intersection of all planes
* - 2 clips the union of all planes
* - 3 clips the complement of all planes