Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
fslpy
Manage
Activity
Members
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Analyze
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
FSL
fslpy
Commits
9e57cdcb
Commit
9e57cdcb
authored
10 years ago
by
Paul McCarthy
Browse files
Options
Downloads
Patches
Plain Diff
Aargh. Everything is broken. Trying to use 3D Texture for storing image data.
parent
6e120eee
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
fsl/data/fslimage.py
+2
-0
2 additions, 0 deletions
fsl/data/fslimage.py
fsl/fslview/slicecanvas.py
+208
-204
208 additions, 204 deletions
fsl/fslview/slicecanvas.py
with
210 additions
and
204 deletions
fsl/data/fslimage.py
+
2
−
0
View file @
9e57cdcb
...
@@ -8,6 +8,7 @@
...
@@ -8,6 +8,7 @@
import
sys
import
sys
import
logging
import
logging
import
traceback
import
collections
import
collections
import
os.path
as
op
import
os.path
as
op
...
@@ -392,3 +393,4 @@ class ImageList(object):
...
@@ -392,3 +393,4 @@ class ImageList(object):
listener
(
self
)
listener
(
self
)
except
Exception
as
e
:
except
Exception
as
e
:
log
.
debug
(
'
Listener raised exception: {}
'
.
format
(
e
.
message
))
log
.
debug
(
'
Listener raised exception: {}
'
.
format
(
e
.
message
))
traceback
.
print_exc
()
This diff is collapsed.
Click to expand it.
fsl/fslview/slicecanvas.py
+
208
−
204
View file @
9e57cdcb
...
@@ -20,6 +20,7 @@ import OpenGL.arrays.vbo as vbo
...
@@ -20,6 +20,7 @@ import OpenGL.arrays.vbo as vbo
# for functionality which is standard in 3.2.
# for functionality which is standard in 3.2.
import
OpenGL.GL.ARB.instanced_arrays
as
arbia
import
OpenGL.GL.ARB.instanced_arrays
as
arbia
import
OpenGL.GL.ARB.draw_instanced
as
arbdi
import
OpenGL.GL.ARB.draw_instanced
as
arbdi
import
OpenGL.GL.ARB.texture_rg
as
arbrg
import
fsl.data.fslimage
as
fslimage
import
fsl.data.fslimage
as
fslimage
...
@@ -57,11 +58,6 @@ class GLImageData(object):
...
@@ -57,11 +58,6 @@ class GLImageData(object):
self
.
image
=
image
self
.
image
=
image
self
.
canvas
=
canvas
self
.
canvas
=
canvas
self
.
imageBuffer
=
None
self
.
colourBuffer
=
None
self
.
positionBuffer
=
None
self
.
geomBuffer
=
None
# Here, x,y, and z refer to screen
# Here, x,y, and z refer to screen
# coordinates, not image coordinates:
# coordinates, not image coordinates:
...
@@ -79,13 +75,6 @@ class GLImageData(object):
...
@@ -79,13 +75,6 @@ class GLImageData(object):
self
.
ylen
=
image
.
pixdim
[
canvas
.
yax
]
self
.
ylen
=
image
.
pixdim
[
canvas
.
yax
]
self
.
zlen
=
image
.
pixdim
[
canvas
.
zax
]
self
.
zlen
=
image
.
pixdim
[
canvas
.
zax
]
dsize
=
image
.
data
.
dtype
.
itemsize
# byte offset along each axis
self
.
xstride
=
image
.
data
.
strides
[
canvas
.
xax
]
/
dsize
self
.
ystride
=
image
.
data
.
strides
[
canvas
.
yax
]
/
dsize
self
.
zstride
=
image
.
data
.
strides
[
canvas
.
zax
]
/
dsize
# Maximum number of colours used to draw image data
# Maximum number of colours used to draw image data
self
.
colourResolution
=
256
self
.
colourResolution
=
256
...
@@ -131,50 +120,51 @@ class GLImageData(object):
...
@@ -131,50 +120,51 @@ class GLImageData(object):
# float32
# float32
positionData
=
image
.
voxToWorld
(
positionData
,
axes
=
(
xax
,
yax
))
positionData
=
image
.
voxToWorld
(
positionData
,
axes
=
(
xax
,
yax
))
positionData
=
np
.
array
(
positionData
,
dtype
=
np
.
float32
)
positionData
=
np
.
array
(
positionData
,
dtype
=
np
.
float32
)
positionData
=
positionData
.
ravel
(
'
C
'
)
# Define GL buffers for the geometry and position
# The image buffers, containing the image data
# data containing the data we just created above
imageBuffers
=
self
.
initImageBuffer
()
geomData
=
geomData
.
ravel
(
order
=
'
C
'
)
screenPosBuffer
=
vbo
.
VBO
(
positionData
,
gl
.
GL_STATIC_DRAW
)
positionData
=
positionData
.
ravel
(
order
=
'
C
'
)
geomBuffer
=
vbo
.
VBO
(
geomData
,
gl
.
GL_STATIC_DRAW
)
geomBuffer
=
vbo
.
VBO
(
geomData
,
gl
.
GL_STATIC_DRAW
)
positionBuffer
=
vbo
.
VBO
(
positionData
,
gl
.
GL_STATIC_DRAW
)
# The image buffer, containing the image data itself
imageBuffer
=
self
.
initImageBuffer
()
# The colour buffer, containing a map of
# colours (stored on the GPU as a 1D texture)
colourBuffer
=
gl
.
glGenTextures
(
1
)
self
.
geomBuffer
=
geomBuffer
self
.
dataBuffer
=
imageBuffers
[
'
dataBuffer
'
]
self
.
positionBuffer
=
positionBuffer
self
.
voxXBuffer
=
imageBuffers
[
'
xBuffer
'
]
self
.
imageBuffer
=
imageBuffer
self
.
voxYBuffer
=
imageBuffers
[
'
yBuffer
'
]
self
.
colourBuffer
=
colourBuffer
self
.
voxZBuffer
=
imageBuffers
[
'
zBuffer
'
]
self
.
screenPosBuffer
=
screenPosBuffer
self
.
geomBuffer
=
geomBuffer
# Add listeners to this image so the view can be
# Add listeners to this image so the view can be
# updated when its display properties are changed
# updated when its display properties are changed
self
.
configDisplayListeners
()
self
.
configDisplayListeners
()
# Create the colour buffer for the given image
self
.
updateColourBuffer
()
def
initImageBuffer
(
self
):
def
initImageBuffer
(
self
):
"""
"""
Initialises the OpenGL buffer used to store the data for the given
Initialises the OpenGL buffer
s
used to store the data for the given
image. The buffer
is
stored as an attribute of the image and, if it
image. The buffer
s are
stored as an attribute of the image and, if it
has already been created (e.g. by another SliceCanvas object), the
has already been created (e.g. by another SliceCanvas object), the
existing buffer is returned.
existing buffer is returned. The value stored on the image, and
the value returned by this method, is a dictionary with the following
keys:
- dataBuffer:
- xBuffer:
- yBuffer:
- zBuffer:
"""
"""
image
=
self
.
image
image
=
self
.
image
try
:
imageBuffer
=
image
.
getAttribute
(
'
glBuffer
'
)
try
:
imageBuffer
=
image
.
getAttribute
(
'
glBuffer
s
'
)
except
:
imageBuffer
=
None
except
:
imageBuffer
=
None
if
imageBuffer
is
not
None
:
if
imageBuffer
is
not
None
:
return
imageBuffer
return
imageBuffer
xlen
=
image
.
shape
[
0
]
ylen
=
image
.
shape
[
1
]
zlen
=
image
.
shape
[
2
]
# The image data is normalised to lie
# The image data is normalised to lie
# between 0 and 255, and cast to uint8
# between 0 and 255, and cast to uint8
imageData
=
np
.
array
(
image
.
data
,
dtype
=
np
.
float32
)
imageData
=
np
.
array
(
image
.
data
,
dtype
=
np
.
float32
)
...
@@ -186,12 +176,61 @@ class GLImageData(object):
...
@@ -186,12 +176,61 @@ class GLImageData(object):
# so the data, as stored on the GPU, has its first
# so the data, as stored on the GPU, has its first
# dimension as the fastest changing.
# dimension as the fastest changing.
imageData
=
imageData
.
ravel
(
order
=
'
F
'
)
imageData
=
imageData
.
ravel
(
order
=
'
F
'
)
imageBuffer
=
vbo
.
VBO
(
imageData
,
gl
.
GL_STATIC_DRAW
)
# Image data is stored on the GPU as a 3D texture
dataBuffer
=
gl
.
glGenTextures
(
1
)
gl
.
glBindTexture
(
gl
.
GL_TEXTURE_3D
,
dataBuffer
)
gl
.
glTexParameteri
(
gl
.
GL_TEXTURE_3D
,
gl
.
GL_TEXTURE_MAG_FILTER
,
gl
.
GL_NEAREST
)
gl
.
glTexParameteri
(
gl
.
GL_TEXTURE_3D
,
gl
.
GL_TEXTURE_MIN_FILTER
,
gl
.
GL_NEAREST
)
gl
.
glTexParameteri
(
gl
.
GL_TEXTURE_3D
,
gl
.
GL_TEXTURE_WRAP_S
,
gl
.
GL_CLAMP_TO_EDGE
)
gl
.
glTexImage3D
(
gl
.
GL_TEXTURE_3D
,
0
,
arbrg
.
GL_R8
,
xlen
,
ylen
,
zlen
,
0
,
gl
.
GL_RED
,
gl
.
GL_UNSIGNED_BYTE
,
imageData
)
# x/y/z coordinates are stored as
# VBO arrays in the range [0, 1]
xstep
=
1.0
/
xlen
ystep
=
1.0
/
ylen
zstep
=
1.0
/
zlen
xData
=
np
.
arange
(
0.0
+
xstep
/
2
,
1.0
+
xstep
/
2
,
1.0
/
xlen
,
dtype
=
np
.
float32
)
yData
=
np
.
arange
(
0.0
+
ystep
/
2
,
1.0
+
ystep
/
2
,
1.0
/
ylen
,
dtype
=
np
.
float32
)
zData
=
np
.
arange
(
0.0
+
zstep
/
2
,
1.0
+
zstep
/
2
,
1.0
/
zlen
,
dtype
=
np
.
float32
)
xBuffer
=
vbo
.
VBO
(
xData
,
gl
.
GL_STATIC_DRAW
)
yBuffer
=
vbo
.
VBO
(
yData
,
gl
.
GL_STATIC_DRAW
)
zBuffer
=
vbo
.
VBO
(
zData
,
gl
.
GL_STATIC_DRAW
)
print
"
Data buffer
"
print
imageData
print
"
X buffer
"
print
xData
print
"
Y buffer
"
print
yData
print
"
Z buffer
"
print
zData
imageBuffer
=
{}
imageBuffer
[
'
dataBuffer
'
]
=
dataBuffer
imageBuffer
[
'
xBuffer
'
]
=
xBuffer
imageBuffer
[
'
yBuffer
'
]
=
yBuffer
imageBuffer
[
'
zBuffer
'
]
=
zBuffer
# And added as an attribute of the image, so
# And added as an attribute of the image, so
# other things which want to render the image
# other things which want to render the image
# don't need to create a
nother
buffer.
# don't need to
re
create a
ll of those
buffer
s
.
image
.
setAttribute
(
'
glBuffer
'
,
imageBuffer
)
image
.
setAttribute
(
'
glBuffer
s
'
,
imageBuffer
)
return
imageBuffer
return
imageBuffer
...
@@ -232,63 +271,6 @@ class GLImageData(object):
...
@@ -232,63 +271,6 @@ class GLImageData(object):
display
.
addListener
(
prop
,
lnrName
.
format
(
prop
),
colourUpdateNeeded
)
display
.
addListener
(
prop
,
lnrName
.
format
(
prop
),
colourUpdateNeeded
)
def
updateColourBuffer
(
self
):
"""
Regenerates the colour buffer used to colour image voxels.
"""
display
=
self
.
image
.
display
colourBuffer
=
self
.
colourBuffer
# Here we are creating a range of values to be passed
# to the matplotlib.colors.Colormap instance of the
# image display. We scale this range such that data
# values which lie outside the configured display range
# will map to values below 0.0 or above 1.0. It is
# assumed that the Colormap instance is configured to
# generate appropriate colours for these out-of-range
# values.
normalRange
=
np
.
linspace
(
0.0
,
1.0
,
self
.
colourResolution
)
normalStep
=
1.0
/
(
self
.
colourResolution
-
1
)
normMin
=
(
display
.
displayMin
-
display
.
dataMin
)
/
\
(
display
.
dataMax
-
display
.
dataMin
)
normMax
=
(
display
.
displayMax
-
display
.
dataMin
)
/
\
(
display
.
dataMax
-
display
.
dataMin
)
newStep
=
normalStep
/
(
normMax
-
normMin
)
newRange
=
(
normalRange
-
normMin
)
*
(
newStep
/
normalStep
)
# Create [self.colourResolution] rgb values,
# spanning the entire range of the image
# colour map
colourmap
=
display
.
cmap
(
newRange
)
# The colour data is stored on
# the GPU as 8 bit rgb triplets
colourmap
=
np
.
floor
(
colourmap
*
255
)
colourmap
=
np
.
array
(
colourmap
,
dtype
=
np
.
uint8
)
colourmap
=
colourmap
.
ravel
(
order
=
'
C
'
)
# GL texture creation stuff
gl
.
glBindTexture
(
gl
.
GL_TEXTURE_1D
,
colourBuffer
)
gl
.
glTexParameteri
(
gl
.
GL_TEXTURE_1D
,
gl
.
GL_TEXTURE_MAG_FILTER
,
gl
.
GL_NEAREST
)
gl
.
glTexParameteri
(
gl
.
GL_TEXTURE_1D
,
gl
.
GL_TEXTURE_MIN_FILTER
,
gl
.
GL_NEAREST
)
gl
.
glTexParameteri
(
gl
.
GL_TEXTURE_1D
,
gl
.
GL_TEXTURE_WRAP_S
,
gl
.
GL_CLAMP_TO_EDGE
)
gl
.
glTexImage1D
(
gl
.
GL_TEXTURE_1D
,
0
,
gl
.
GL_RGBA8
,
self
.
colourResolution
,
0
,
gl
.
GL_RGBA
,
gl
.
GL_UNSIGNED_BYTE
,
colourmap
)
# The vertex shader positions and colours a single vertex.
# The vertex shader positions and colours a single vertex.
vertex_shader
=
"""
vertex_shader
=
"""
...
@@ -297,14 +279,19 @@ vertex_shader = """
...
@@ -297,14 +279,19 @@ vertex_shader = """
/* Opacity - constant for a whole image */
/* Opacity - constant for a whole image */
uniform float alpha;
uniform float alpha;
/* image data texture */
uniform sampler3D dataBuffer;
/* Current vertex */
/* Current vertex */
attribute vec2 inVertex;
attribute vec2 inVertex;
/*
Position of the current voxel
*/
/*
Current screen coordinates
*/
attribute vec2
i
nPos;
attribute vec2
scree
nPos;
/* Value of the current voxel (in range [0,1]) */
/* voxel coordinates */
attribute float voxValue;
attribute float voxX;
attribute float voxY;
attribute float voxZ;
/* Voxel value passed through to fragment shader */
/* Voxel value passed through to fragment shader */
varying float fragVoxValue;
varying float fragVoxValue;
...
@@ -316,33 +303,28 @@ void main(void) {
...
@@ -316,33 +303,28 @@ void main(void) {
* (and perform standard transformation from data
* (and perform standard transformation from data
* coordinates to screen coordinates).
* coordinates to screen coordinates).
*/
*/
gl_Position = gl_ModelViewProjectionMatrix *
\
gl_Position = gl_ModelViewProjectionMatrix *
\
vec4(inVertex
+i
nPos, 0.0, 1.0);
vec4(inVertex
+ scree
nPos, 0.0, 1.0);
/* Pass the voxel value through to the shader. */
/* Pass the voxel value through to the shader. */
fragVoxValue = voxValue;
vec4 vt = texture3D(dataBuffer, vec3(voxX, voxY, voxZ));
fragVoxValue = vt.r;
}
}
"""
"""
#
Fragment
shader. Given the current voxel value, looks
#
Buffer
shader. Given the current voxel value, looks
# up the appropriate colour in the colour buffer.
# up the appropriate colour in the colour buffer.
fragment_shader
=
"""
fragment_shader
=
"""
#version 120
#version 120
uniform float alpha;
uniform float alpha;
uniform sampler1D colourMap; /* RGB colour map, stored as a 1D texture */
varying float fragVoxValue;
varying float fragVoxValue;
void main(void) {
void main(void) {
vec4 voxTexture = texture1D(colourMap, fragVoxValue);
vec3 voxColour = vec3(fragVoxValue, fragVoxValue, fragVoxValue);
vec3 voxColour = voxTexture.rgb;
float voxAlpha = alpha;
float voxAlpha = voxTexture.a;
if (voxAlpha > alpha) {
voxAlpha = alpha;
}
gl_FragColor = vec4(voxColour, voxAlpha);
gl_FragColor = vec4(voxColour, voxAlpha);
}
}
...
@@ -551,16 +533,6 @@ class SliceCanvas(wxgl.GLCanvas):
...
@@ -551,16 +533,6 @@ class SliceCanvas(wxgl.GLCanvas):
of this SliceCanvas object. This method is only called
of this SliceCanvas object. This method is only called
once, on the first draw.
once, on the first draw.
"""
"""
# A bit hacky. We can only set the GL context (and create
# the GL data) once something is actually displayed on the
# screen. The _initGLData method is called (asynchronously)
# by the draw() method if it sees that the glReady flag has
# not yet been set. But draw() may be called mored than once
# before _initGLData is called. Here, to prevent
# _initGLData from running more than once, the first time
# it is called it simply overwrites itself with a dummy method.
self
.
_initGLData
=
lambda
s
:
s
self
.
context
.
SetCurrent
(
self
)
self
.
context
.
SetCurrent
(
self
)
...
@@ -568,17 +540,33 @@ class SliceCanvas(wxgl.GLCanvas):
...
@@ -568,17 +540,33 @@ class SliceCanvas(wxgl.GLCanvas):
shaders
.
compileShader
(
vertex_shader
,
gl
.
GL_VERTEX_SHADER
),
shaders
.
compileShader
(
vertex_shader
,
gl
.
GL_VERTEX_SHADER
),
shaders
.
compileShader
(
fragment_shader
,
gl
.
GL_FRAGMENT_SHADER
))
shaders
.
compileShader
(
fragment_shader
,
gl
.
GL_FRAGMENT_SHADER
))
# Indices of all vertex/fragment shader parameters
# Indices of all vertex/fragment shader parameters
self
.
inVertexPos
=
gl
.
glGetAttribLocation
(
self
.
shaders
,
'
inVertex
'
)
self
.
alphaPos
=
gl
.
glGetUniformLocation
(
self
.
shaders
,
'
alpha
'
)
self
.
voxelValuePos
=
gl
.
glGetAttribLocation
(
self
.
shaders
,
'
voxValue
'
)
self
.
dataBufferPos
=
gl
.
glGetUniformLocation
(
self
.
shaders
,
self
.
inPositionPos
=
gl
.
glGetAttribLocation
(
self
.
shaders
,
'
inPos
'
)
'
dataBuffer
'
)
self
.
alphaPos
=
gl
.
glGetUniformLocation
(
self
.
shaders
,
'
alpha
'
)
self
.
inVertexPos
=
gl
.
glGetAttribLocation
(
self
.
shaders
,
self
.
colourMapPos
=
gl
.
glGetUniformLocation
(
self
.
shaders
,
'
colourMap
'
)
'
inVertex
'
)
self
.
screenPosPos
=
gl
.
glGetAttribLocation
(
self
.
shaders
,
'
screenPos
'
)
self
.
voxXPos
=
gl
.
glGetAttribLocation
(
self
.
shaders
,
'
voxX
'
)
self
.
voxYPos
=
gl
.
glGetAttribLocation
(
self
.
shaders
,
'
voxY
'
)
self
.
voxZPos
=
gl
.
glGetAttribLocation
(
self
.
shaders
,
'
voxZ
'
)
# Initialise data for the images that
# Initialise data for the images that
# are already in the image list
# are already in the image list
self
.
_imageListChanged
()
self
.
_imageListChanged
()
# A bit hacky. We can only set the GL context (and create
# the GL data) once something is actually displayed on the
# screen. The _initGLData method is called (asynchronously)
# by the draw() method if it sees that the glReady flag has
# not yet been set. But draw() may be called mored than once
# before _initGLData is called. Here, to prevent
# _initGLData from running more than once, the first time
# it is called it simply overwrites itself with a dummy method.
self
.
_initGLData
=
lambda
s
:
s
self
.
glReady
=
True
self
.
glReady
=
True
...
@@ -590,7 +578,7 @@ class SliceCanvas(wxgl.GLCanvas):
...
@@ -590,7 +578,7 @@ class SliceCanvas(wxgl.GLCanvas):
"""
"""
size
=
self
.
GetSize
()
size
=
self
.
GetSize
()
# set up 2D drawing
# set up 2D drawing
gl
.
glViewport
(
0
,
0
,
size
.
width
,
size
.
height
)
gl
.
glViewport
(
0
,
0
,
size
.
width
,
size
.
height
)
gl
.
glMatrixMode
(
gl
.
GL_PROJECTION
)
gl
.
glMatrixMode
(
gl
.
GL_PROJECTION
)
...
@@ -616,6 +604,7 @@ class SliceCanvas(wxgl.GLCanvas):
...
@@ -616,6 +604,7 @@ class SliceCanvas(wxgl.GLCanvas):
# clear the canvas
# clear the canvas
gl
.
glClear
(
gl
.
GL_COLOR_BUFFER_BIT
|
gl
.
GL_DEPTH_BUFFER_BIT
)
gl
.
glClear
(
gl
.
GL_COLOR_BUFFER_BIT
|
gl
.
GL_DEPTH_BUFFER_BIT
)
# load the shaders
gl
.
glUseProgram
(
self
.
shaders
)
gl
.
glUseProgram
(
self
.
shaders
)
# enable transparency
# enable transparency
...
@@ -637,17 +626,16 @@ class SliceCanvas(wxgl.GLCanvas):
...
@@ -637,17 +626,16 @@ class SliceCanvas(wxgl.GLCanvas):
imageDisplay
=
image
.
display
imageDisplay
=
image
.
display
geomBuffer
=
glImageData
.
geomBuffer
dataBuffer
=
glImageData
.
dataBuffer
imageBuffer
=
glImageData
.
imageBuffer
voxXBuffer
=
glImageData
.
voxXBuffer
positionBuffer
=
glImageData
.
positionBuffer
voxYBuffer
=
glImageData
.
voxYBuffer
colourBuffer
=
glImageData
.
colourBuffer
voxZBuffer
=
glImageData
.
voxZBuffer
geomBuffer
=
glImageData
.
geomBuffer
xdim
=
glImageData
.
xdim
screenPosBuffer
=
glImageData
.
screenPosBuffer
ydim
=
glImageData
.
ydim
zdim
=
glImageData
.
zdim
xdim
=
glImageData
.
xdim
xstride
=
glImageData
.
xstride
ydim
=
glImageData
.
ydim
ystride
=
glImageData
.
ystride
zdim
=
glImageData
.
zdim
zstride
=
glImageData
.
zstride
# Don't draw the slice if this
# Don't draw the slice if this
# image display is disabled
# image display is disabled
...
@@ -656,79 +644,95 @@ class SliceCanvas(wxgl.GLCanvas):
...
@@ -656,79 +644,95 @@ class SliceCanvas(wxgl.GLCanvas):
# Figure out which slice we are drawing,
# Figure out which slice we are drawing,
# and if it's out of range, don't draw it
# and if it's out of range, don't draw it
zi
=
int
(
image
.
worldToVox
(
self
.
zpos
,
self
.
zax
))
zi
=
int
(
image
.
worldToVox
(
self
.
zpos
,
self
.
zax
))
if
zi
<
0
or
zi
>=
zdim
:
continue
if
zi
<
0
or
zi
>=
zdim
:
continue
# Set up the colour buffer
voxOffs
=
[
0
,
0
,
0
]
gl
.
glEnable
(
gl
.
GL_TEXTURE_1D
)
voxSteps
=
[
1
,
1
,
1
]
gl
.
glActiveTexture
(
gl
.
GL_TEXTURE0
)
gl
.
glBindTexture
(
gl
.
GL_TEXTURE_1D
,
colourBuffer
)
gl
.
glUniform1i
(
self
.
colourMapPos
,
0
)
voxOffs
[
self
.
zax
]
=
zi
voxSteps
[
self
.
yax
]
=
xdim
voxSteps
[
self
.
zax
]
=
xdim
*
ydim
# bind the current alpha value to the
# shader alpha variable
gl
.
glUniform1f
(
self
.
alphaPos
,
imageDisplay
.
alpha
)
gl
.
glUniform1f
(
self
.
alphaPos
,
imageDisplay
.
alpha
)
# We draw each horizontal row of voxels one at a time.
# bind the transformation matrix
# This is necessary because, in order to allow image
# to the shader variable
# buffers to be shared between different SliceCanvas
# gl.glUniformMatrix4fv(self.voxToWorldMatPos,
# objects, we cannot re-arrange the image data, as
# 1, False, transformBuffer)
# stored in GPU memory. So while the memory offset
# between values in the same row (or column) is
# consistent, the offset between rows (columns) is
# not. And drawing rows seems to be faster than
# drawing columns, for reasons unknown to me.
for
yi
in
range
(
ydim
):
imageOffset
=
zi
*
zstride
+
yi
*
ystride
imageStride
=
xstride
posOffset
=
yi
*
xdim
*
8
# The geometry buffer, which defines the geometry of a
# single vertex (4 vertices, drawn as a triangle strip)
geomBuffer
.
bind
()
gl
.
glVertexAttribPointer
(
self
.
inVertexPos
,
2
,
gl
.
GL_FLOAT
,
gl
.
GL_FALSE
,
0
,
None
)
gl
.
glEnableVertexAttribArray
(
self
.
inVertexPos
)
arbia
.
glVertexAttribDivisorARB
(
self
.
inVertexPos
,
0
)
# The position buffer, which defines
# Set up the colour buffer
# the location of every voxel
# gl.glEnable(gl.GL_TEXTURE_1D)
positionBuffer
.
bind
()
# gl.glActiveTexture(gl.GL_TEXTURE0)
# gl.glBindTexture(gl.GL_TEXTURE_1D, colourBuffer)
# gl.glUniform1i(self.colourMapPos, 0)
# Set up the image data buffer
gl
.
glEnable
(
gl
.
GL_TEXTURE_3D
)
# change to texxture 1 when you get working
gl
.
glActiveTexture
(
gl
.
GL_TEXTURE0
)
gl
.
glBindTexture
(
gl
.
GL_TEXTURE_3D
,
dataBuffer
)
gl
.
glUniform1i
(
self
.
dataBufferPos
,
0
)
# Screen x positions
screenPosBuffer
.
bind
()
gl
.
glVertexAttribPointer
(
self
.
screenPosPos
,
2
,
gl
.
GL_FLOAT
,
gl
.
GL_FALSE
,
0
,
None
)
gl
.
glEnableVertexAttribArray
(
self
.
screenPosPos
)
arbia
.
glVertexAttribDivisorARB
(
self
.
screenPosPos
,
1
)
for
buf
,
pos
,
step
,
off
in
zip
(
(
voxXBuffer
,
voxYBuffer
,
voxZBuffer
),
(
self
.
voxXPos
,
self
.
voxYPos
,
self
.
voxZPos
),
voxSteps
,
voxOffs
):
buf
.
bind
()
gl
.
glVertexAttribPointer
(
gl
.
glVertexAttribPointer
(
self
.
inPositionP
os
,
p
os
,
2
,
1
,
gl
.
GL_FLOAT
,
gl
.
GL_FLOAT
,
gl
.
GL_FALSE
,
gl
.
GL_FALSE
,
0
,
0
,
positionBuffer
+
posOffset
)
buf
+
off
*
4
)
gl
.
glEnableVertexAttribArray
(
self
.
inPositionPos
)
gl
.
glEnableVertexAttribArray
(
pos
)
arbia
.
glVertexAttribDivisorARB
(
self
.
inPositionPos
,
1
)
arbia
.
glVertexAttribDivisorARB
(
pos
,
step
)
# The image buffer, which defines
# The geometry buffer, which defines the geometry of a
# the colour value at each voxel.
# single vertex (4 vertices, drawn as a triangle strip)
imageBuffer
.
bind
()
geomBuffer
.
bind
()
gl
.
glVertexAttribPointer
(
gl
.
glVertexAttribPointer
(
self
.
voxelValuePos
,
self
.
inVertexPos
,
1
,
2
,
gl
.
GL_UNSIGNED_BYTE
,
gl
.
GL_FLOAT
,
gl
.
GL_TRUE
,
gl
.
GL_FALSE
,
imageStride
,
0
,
imageBuffer
+
imageOffset
)
None
)
gl
.
glEnableVertexAttribArray
(
self
.
inVertexPos
)
gl
.
glEnableVertexAttribArray
(
self
.
voxelValuePos
)
arbia
.
glVertexAttribDivisorARB
(
self
.
inVertexPos
,
0
)
arbia
.
glVertexAttribDivisorARB
(
self
.
voxelValuePos
,
1
)
# Draw all of the triangles!
print
'
Draw {} voxels from slice {} ({} {} {})
'
.
format
(
arbdi
.
glDrawArraysInstancedARB
(
xdim
*
ydim
,
zi
,
self
.
xax
,
self
.
yax
,
self
.
zax
)
gl
.
GL_TRIANGLE_STRIP
,
0
,
4
,
xdim
)
print
"
Offsets: {}
"
.
format
(
voxOffs
)
print
"
Steps: {}
"
.
format
(
voxSteps
)
gl
.
glDisableVertexAttribArray
(
self
.
inVertexPos
)
gl
.
glDisableVertexAttribArray
(
self
.
inPositionPos
)
arbdi
.
glDrawArraysInstancedARB
(
gl
.
glDisableVertexAttribArray
(
self
.
voxelValuePos
)
gl
.
GL_TRIANGLE_STRIP
,
0
,
4
,
xdim
*
ydim
)
gl
.
glDisable
(
gl
.
GL_TEXTURE_1D
)
gl
.
glDisableVertexAttribArray
(
self
.
inVertexPos
)
gl
.
glDisableVertexAttribArray
(
self
.
screenPosPos
)
gl
.
glDisableVertexAttribArray
(
self
.
voxXPos
)
gl
.
glDisableVertexAttribArray
(
self
.
voxYPos
)
gl
.
glDisableVertexAttribArray
(
self
.
voxZPos
)
gl
.
glDisable
(
gl
.
GL_TEXTURE_1D
)
gl
.
glDisable
(
gl
.
GL_TEXTURE_3D
)
gl
.
glUseProgram
(
0
)
gl
.
glUseProgram
(
0
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment