From 14c66cdc24b12fb11641eb55b2f36402e1bb7fd8 Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Thu, 9 Apr 2015 10:24:40 +0100 Subject: [PATCH] Experimenting with the simplest possible rendering approach I can manage --- fsl/data/image.py | 1 + fsl/fslview/displaycontext/display.py | 1 + fsl/fslview/gl/__init__.py | 1 + fsl/fslview/gl/gl21/__init__.py | 1 + fsl/fslview/gl/gl21/gltest_frag.glsl | 16 ++++ fsl/fslview/gl/gl21/gltest_funcs.py | 103 ++++++++++++++++++++++++ fsl/fslview/gl/gl21/gltest_vert.glsl | 11 +++ fsl/fslview/gl/globject.py | 2 + fsl/fslview/gl/gltest.py | 109 ++++++++++++++++++++++++++ fsl/fslview/gl/shaders.py | 2 + fsl/fslview/gl/textures/texture.py | 2 +- 11 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 fsl/fslview/gl/gl21/gltest_frag.glsl create mode 100644 fsl/fslview/gl/gl21/gltest_funcs.py create mode 100644 fsl/fslview/gl/gl21/gltest_vert.glsl create mode 100644 fsl/fslview/gl/gltest.py diff --git a/fsl/data/image.py b/fsl/data/image.py index e2af8913c..ac1131c4c 100644 --- a/fsl/data/image.py +++ b/fsl/data/image.py @@ -69,6 +69,7 @@ class Image(props.HasProperties): collections.OrderedDict([ ('volume', '3D/4D volume'), ('mask', '3D/4D mask image'), + ('test', 'I don\'t really know'), ('vector', '3-direction vector image')]), default='volume') """This property defines the type of image data.""" diff --git a/fsl/fslview/displaycontext/display.py b/fsl/fslview/displaycontext/display.py index 81367cac7..032ec2aad 100644 --- a/fsl/fslview/displaycontext/display.py +++ b/fsl/fslview/displaycontext/display.py @@ -351,6 +351,7 @@ class Display(props.SyncableHasProperties): optsMap = { 'volume' : volumeopts.VolumeOpts, + 'test' : volumeopts.VolumeOpts, 'vector' : vectoropts.VectorOpts, 'mask' : maskopts. MaskOpts } diff --git a/fsl/fslview/gl/__init__.py b/fsl/fslview/gl/__init__.py index 76f26233f..06d8a2d51 100644 --- a/fsl/fslview/gl/__init__.py +++ b/fsl/fslview/gl/__init__.py @@ -209,6 +209,7 @@ def bootstrap(glVersion=None): except IndexError: pass thismod.GL_VERSION = verstr + thismod.gltest_funcs = glpkg.gltest_funcs thismod.glvolume_funcs = glpkg.glvolume_funcs thismod.glvector_funcs = glpkg.glvector_funcs thismod._bootstrapped = True diff --git a/fsl/fslview/gl/gl21/__init__.py b/fsl/fslview/gl/gl21/__init__.py index 5f5a552bc..d291eb7b6 100644 --- a/fsl/fslview/gl/gl21/__init__.py +++ b/fsl/fslview/gl/gl21/__init__.py @@ -7,3 +7,4 @@ import glvolume_funcs import glvector_funcs +import gltest_funcs diff --git a/fsl/fslview/gl/gl21/gltest_frag.glsl b/fsl/fslview/gl/gl21/gltest_frag.glsl new file mode 100644 index 000000000..500674c4d --- /dev/null +++ b/fsl/fslview/gl/gl21/gltest_frag.glsl @@ -0,0 +1,16 @@ +#version 120 + +uniform sampler1D colourTexture; +uniform sampler3D imageTexture; +uniform mat4 voxValueXform; + +varying vec3 fragTexCoord; + +void main(void) { + + float value = texture3D(imageTexture, fragTexCoord).x; + + value = (voxValueXform * vec4(value, 0, 0, 0)).x; + + gl_FragColor = texture1D(colourTexture, value); +} diff --git a/fsl/fslview/gl/gl21/gltest_funcs.py b/fsl/fslview/gl/gl21/gltest_funcs.py new file mode 100644 index 000000000..52b5259a7 --- /dev/null +++ b/fsl/fslview/gl/gl21/gltest_funcs.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +# +# gltest_funcs.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +import logging + +import OpenGL.GL as gl + +import fsl.utils.transform as transform +import fsl.fslview.gl.shaders as shaders + +log = logging.getLogger(__name__) + +def init(self): + + vertShaderSrc = shaders.getVertexShader( self) + fragShaderSrc = shaders.getFragmentShader(self) + + self.shaders = shaders.compileShaders(vertShaderSrc, fragShaderSrc) + + self.colourTexturePos = gl.glGetUniformLocation(self.shaders, 'colourTexture') + self.imageTexturePos = gl.glGetUniformLocation(self.shaders, 'imageTexture') + self.voxValueXformPos = gl.glGetUniformLocation(self.shaders, 'voxValueXform') + + self.vertexPos = gl.glGetAttribLocation(self.shaders, 'vertex') + self.texCoordPos = gl.glGetAttribLocation(self.shaders, 'texCoord') + + self.vertexBuffer = gl.glGenBuffers(1) + self.indexBuffer = gl.glGenBuffers(1) + self.texCoordBuffer = gl.glGenBuffers(1) + + +def destroy(self): + pass + + +def preDraw(self): + + gl.glUseProgram(self.shaders) + + voxValueXform = transform.concat( + self.imageTexture.voxValXform, + self.colourTexture.getCoordinateTransform()).ravel('C') + + gl.glUniformMatrix4fv( + self.voxValueXformPos, + 1, + False, + voxValueXform) + + gl.glUniform1i(self.imageTexturePos, 0) + gl.glUniform1i(self.colourTexturePos, 1) + + +def draw(self, vertices, indices, texCoords): + + gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertexBuffer) + gl.glBufferData(gl.GL_ARRAY_BUFFER, + vertices.nbytes, + vertices, + gl.GL_STATIC_DRAW) + gl.glVertexAttribPointer( + self.vertexPos, + 3, + gl.GL_FLOAT, + gl.GL_FALSE, + 0, + None) + gl.glEnableVertexAttribArray(self.vertexPos) + + gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.texCoordBuffer) + gl.glBufferData(gl.GL_ARRAY_BUFFER, + texCoords.nbytes, + texCoords, + gl.GL_STATIC_DRAW) + gl.glVertexAttribPointer( + self.texCoordPos, + 3, + gl.GL_FLOAT, + gl.GL_FALSE, + 0, + None) + gl.glEnableVertexAttribArray(self.texCoordPos) + + gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.indexBuffer) + gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, + indices.nbytes, + indices, + gl.GL_STATIC_DRAW) + + gl.glDrawElements(gl.GL_TRIANGLE_STRIP, 4, gl.GL_UNSIGNED_INT, None) + + +def postDraw(self): + + gl.glDisableVertexAttribArray(self.vertexPos) + gl.glDisableVertexAttribArray(self.texCoordPos) + gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0) + gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, 0) + gl.glUseProgram(0) diff --git a/fsl/fslview/gl/gl21/gltest_vert.glsl b/fsl/fslview/gl/gl21/gltest_vert.glsl new file mode 100644 index 000000000..f935123e4 --- /dev/null +++ b/fsl/fslview/gl/gl21/gltest_vert.glsl @@ -0,0 +1,11 @@ +#version 120 + +attribute vec3 vertex; +attribute vec3 texCoord; +varying vec3 fragTexCoord; + +void main(void) { + + fragTexCoord = texCoord; + gl_Position = gl_ModelViewProjectionMatrix * vec4(vertex, 1); +} diff --git a/fsl/fslview/gl/globject.py b/fsl/fslview/gl/globject.py index 82837ee3f..83f89fa46 100644 --- a/fsl/fslview/gl/globject.py +++ b/fsl/fslview/gl/globject.py @@ -37,11 +37,13 @@ def createGLObject(image, display): import fsl.fslview.gl.glvolume as glvolume import fsl.fslview.gl.glmask as glmask + import fsl.fslview.gl.gltest as gltest import fsl.fslview.gl.glvector as glvector _objectmap = { 'volume' : glvolume.GLVolume, 'mask' : glmask .GLMask, + 'test' : gltest .GLTest, 'vector' : glvector.GLVector } diff --git a/fsl/fslview/gl/gltest.py b/fsl/fslview/gl/gltest.py new file mode 100644 index 000000000..c1129f8c4 --- /dev/null +++ b/fsl/fslview/gl/gltest.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# +# gltest.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +import logging + + +import numpy as np +import OpenGL.GL as gl + +import fsl.fslview.gl as fslgl +import fsl.fslview.gl.textures as textures +import fsl.fslview.gl.globject as globject +import fsl.utils.transform as transform + + +log = logging.getLogger(__name__) + + +class GLTest(globject.GLImageObject): + + def __init__(self, image, display): + globject.GLImageObject.__init__(self, image, display) + + texName = '{}_{}'.format(id(self.image), type(self).__name__) + + self.colourTexture = textures.ColourMapTexture(texName) + self.imageTexture = textures.getTexture( + textures.ImageTexture, + texName, + self.image, + self.display) + + + fslgl.gltest_funcs.init(self) + + self.refreshColourTexture() + + + def refreshColourTexture(self): + display = self.display + opts = self.displayOpts + + alpha = display.alpha / 100.0 + cmap = opts.cmap + invert = opts.invert + dmin = opts.displayRange[0] + dmax = opts.displayRange[1] + + self.colourTexture.set(cmap=cmap, + invert=invert, + alpha=alpha, + displayRange=(dmin, dmax)) + + + + def destroy(self): + self.colourTexture.destroy() + textures.deleteTexture(self.imageTexture) + + self.colourTexture = None + self.imageTexture = None + + fslgl.gltest_funcs.destroy(self) + + + def setAxes(self, xax, yax): + self.xax = xax + self.yax = yax + self.zax = 3 - xax - yax + + + def preDraw(self): + + self.imageTexture .bindTexture(gl.GL_TEXTURE0) + self.colourTexture.bindTexture(gl.GL_TEXTURE1) + fslgl.gltest_funcs.preDraw(self) + + + def draw(self, zpos, xform=None): + + voxToDisplayMat = self.display.getTransform('voxel', 'display') + displayToVoxMat = self.display.getTransform('display', 'voxel') + + vertices, indices = globject.slice2D( + self.image.shape[:3], + self.xax, + self.yax, + voxToDisplayMat) + + vertices[:, self.zax] = zpos + + texCoords = transform.transform(vertices, displayToVoxMat) + texCoords /= self.image.shape[:3] + + vertices = np.array(vertices, dtype=np.float32).ravel('C') + texCoords = np.array(texCoords, dtype=np.float32).ravel('C') + indices = np.array(indices, dtype=np.uint32) .ravel('C') + + fslgl.gltest_funcs.draw(self, vertices, indices, texCoords) + + + def postDraw(self): + self.imageTexture .unbindTexture() + self.colourTexture.unbindTexture() + fslgl.gltest_funcs.postDraw(self) diff --git a/fsl/fslview/gl/shaders.py b/fsl/fslview/gl/shaders.py index 17f8967ca..f02c4e7ac 100644 --- a/fsl/fslview/gl/shaders.py +++ b/fsl/fslview/gl/shaders.py @@ -220,9 +220,11 @@ def _getFileName(globj, shaderType): # than passing a GLObject instance import fsl.fslview.gl.glvolume as glvolume import fsl.fslview.gl.glvector as glvector + import fsl.fslview.gl.gltest as gltest if isinstance(globj, str): prefix = globj elif isinstance(globj, glvolume.GLVolume): prefix = 'glvolume' + elif isinstance(globj, gltest .GLTest): prefix = 'gltest' elif isinstance(globj, glvector.GLVector): prefix = 'glvector' else: raise RuntimeError('Unknown GL object type: ' diff --git a/fsl/fslview/gl/textures/texture.py b/fsl/fslview/gl/textures/texture.py index 626d7d895..5936e0997 100644 --- a/fsl/fslview/gl/textures/texture.py +++ b/fsl/fslview/gl/textures/texture.py @@ -202,7 +202,7 @@ class Texture2D(Texture): self.unbindTexture() gl.glDisableClientState(gl.GL_VERTEX_ARRAY) - gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY) + gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY) def drawOnBounds(self, xmin, xmax, ymin, ymax, xax, yax): -- GitLab