diff --git a/fsl/fsleyes/controls/overlaydisplaypanel.py b/fsl/fsleyes/controls/overlaydisplaypanel.py index 6091f21ac32a46415e51690a78fc6e9c13a23553..00a877ea1fa56f5458195fa191f1bbdbff34d73d 100644 --- a/fsl/fsleyes/controls/overlaydisplaypanel.py +++ b/fsl/fsleyes/controls/overlaydisplaypanel.py @@ -336,7 +336,10 @@ _DISPLAY_PROPS = td.TypeDict({ 'VectorOpts' : [ props.Widget('colourImage', labels=_imageName), - props.Widget('modulateImage', labels=_imageName), + props.Widget('modulateImage', + labels=_imageName, + dependencies=['colourImage'], + enabledWhen=lambda o, ci: ci is None), props.Widget('clipImage', labels=_imageName), props.Widget('cmap', dependencies=['colourImage'], diff --git a/fsl/fsleyes/gl/gl21/gllinevector_funcs.py b/fsl/fsleyes/gl/gl21/gllinevector_funcs.py index cb9617ccb3258a557bd03f94658c93c768d532d2..3716cf36079d7e12aee524610a155d79d191d7d2 100644 --- a/fsl/fsleyes/gl/gl21/gllinevector_funcs.py +++ b/fsl/fsleyes/gl/gl21/gllinevector_funcs.py @@ -22,14 +22,12 @@ vector. import logging -import numpy as np -import OpenGL.GL as gl -import OpenGL.raw.GL._types as gltypes +import numpy as np +import OpenGL.GL as gl -import fsl.utils.transform as transform -import fsl.fsleyes.gl.routines as glroutines -import fsl.fsleyes.gl.shaders as shaders -import glvector_funcs +import fsl.utils.transform as transform +import fsl.fsleyes.gl.routines as glroutines +import glvector_funcs log = logging.getLogger(__name__) @@ -44,10 +42,7 @@ def init(self): :class:`.Image` overlay. """ - self.shaders = None - self.vertexBuffer = gl.glGenBuffers(1) - self.texCoordBuffer = gl.glGenBuffers(1) - self.vertexIDBuffer = gl.glGenBuffers(1) + self.shader = None compileShaders( self) updateShaderState(self) @@ -58,10 +53,7 @@ def destroy(self): removes property listeners from the :class:`.LineVectorOpts` instance. """ - gl.glDeleteBuffers(1, gltypes.GLuint(self.vertexBuffer)) - gl.glDeleteBuffers(1, gltypes.GLuint(self.vertexIDBuffer)) - gl.glDeleteBuffers(1, gltypes.GLuint(self.texCoordBuffer)) - gl.glDeleteProgram(self.shaders) + self.shader.delete() def compileShaders(self): @@ -69,28 +61,21 @@ def compileShaders(self): shader variables as attributes of the :class:`.GLLineVector`. """ - vertAtts = ['vertex', 'vertexID'] - vertUniforms = ['imageTexture', 'displayToVoxMat', 'voxToDisplayMat', - 'voxelOffset', 'voxValXform', 'imageShape', - 'directed', 'imageDims'] - - glvector_funcs.compileShaders(self, vertAtts, vertUniforms) + self.shader = glvector_funcs.compileShaders(self) def updateShaderState(self): """Updates all variables used by the vertex/fragment shaders. """ - - gl.glUseProgram(self.shaders) + shader = self.shader + shader.load() + glvector_funcs.updateFragmentShaderState(self) image = self.vectorImage opts = self.displayOpts - svars = self.shaderVars vvxMat = self.imageTexture.voxValXform - imageShape = np.array(image.shape[:3], dtype=np.float32) - directed = opts.directed imageDims = image.pixdim[:3] d2vMat = opts.getTransform('display', 'voxel') @@ -100,32 +85,23 @@ def updateShaderState(self): # transformed voxel coordinates, so # it can floor them to get integer # voxel coordinates - offset = [0.5, 0.5, 0.5] - - offset = np.array(offset, dtype=np.float32) - imageDims = np.array(imageDims, dtype=np.float32) - d2vMat = np.array(d2vMat, dtype=np.float32).ravel('C') - v2dMat = np.array(v2dMat, dtype=np.float32).ravel('C') - vvxMat = np.array(vvxMat, dtype=np.float32).ravel('C') - - gl.glUniform1i( svars['imageTexture'], 0) - gl.glUniformMatrix4fv(svars['displayToVoxMat'], 1, False, d2vMat) - gl.glUniformMatrix4fv(svars['voxToDisplayMat'], 1, False, v2dMat) - gl.glUniformMatrix4fv(svars['voxValXform'], 1, False, vvxMat) - - gl.glUniform3fv(svars['voxelOffset'], 1, offset) - gl.glUniform3fv(svars['imageShape'], 1, imageShape) - gl.glUniform3fv(svars['imageDims'], 1, imageDims) - gl.glUniform1f( svars['directed'], directed) + offset = [0.5, 0.5, 0.5] + + shader.set('displayToVoxMat', d2vMat) + shader.set('voxToDisplayMat', v2dMat) + shader.set('voxValXform', vvxMat) + shader.set('voxelOffset', offset) + shader.set('imageDims', imageDims) + shader.set('directed', directed) - gl.glUseProgram(0) + shader.unload() def preDraw(self): """Prepares the GL state for drawing. This amounts to loading the vertex/fragment shader programs. """ - gl.glUseProgram(self.shaders) + self.shader.load() def draw(self, zpos, xform=None): @@ -137,9 +113,9 @@ def draw(self, zpos, xform=None): image = self.vectorImage opts = self.displayOpts - svars = self.shaderVars + shader = self.shader v2dMat = opts.getTransform('voxel', 'display') - resolution = np.array([opts.resolution] * 3) + resolution = [opts.resolution] * 3 if opts.transform == 'id': resolution = resolution / min(image.pixdim[:3]) @@ -157,37 +133,19 @@ def draw(self, zpos, xform=None): vertices = np.repeat(vertices, 2, 0) indices = np.arange(vertices.shape[0], dtype=np.uint32) - vertices = vertices.ravel('C') if xform is None: xform = v2dMat else: xform = transform.concat(v2dMat, xform) + + shader.set( 'voxToDisplayMat', xform) + shader.setAtt('vertexID', indices) + shader.setAtt('vertex', vertices) + shader.loadAtts() - xform = np.array(xform, dtype=np.float32).ravel('C') - gl.glUniformMatrix4fv(svars['voxToDisplayMat'], 1, False, xform) - - # bind the vertex ID buffer - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertexIDBuffer) - gl.glBufferData( - gl.GL_ARRAY_BUFFER, indices.nbytes, indices, gl.GL_STATIC_DRAW) - gl.glVertexAttribPointer( - svars['vertexID'], 1, gl.GL_UNSIGNED_INT, gl.GL_FALSE, 0, None) - - # and the vertex buffer - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertexBuffer) - gl.glBufferData( - gl.GL_ARRAY_BUFFER, vertices.nbytes, vertices, gl.GL_STATIC_DRAW) - gl.glVertexAttribPointer( - svars['vertex'], 3, gl.GL_FLOAT, gl.GL_FALSE, 0, None) - - gl.glEnableVertexAttribArray(svars['vertex']) - gl.glEnableVertexAttribArray(svars['vertexID']) - gl.glLineWidth(opts.lineWidth) gl.glDrawArrays(gl.GL_LINES, 0, vertices.size / 3) - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0) - gl.glDisableVertexAttribArray(svars['vertexID']) - gl.glDisableVertexAttribArray(svars['vertex']) + shader.unloadAtts() def drawAll(self, zposes, xforms): @@ -199,4 +157,4 @@ def drawAll(self, zposes, xforms): def postDraw(self): """Clears the GL state after drawing. """ - gl.glUseProgram(0) + self.shader.unload() diff --git a/fsl/fsleyes/gl/glsl/program.py b/fsl/fsleyes/gl/glsl/program.py index a150ffc5a91ac34f706b0bc2d0762a3a6cca9fd7..31370b11ab46863398e93ad8671b5fae25dd8a23 100644 --- a/fsl/fsleyes/gl/glsl/program.py +++ b/fsl/fsleyes/gl/glsl/program.py @@ -89,12 +89,12 @@ class ShaderProgram(object): def unloadAtts(self): for att in self.vertAttributes: - gl.glDisableVertexAttribArray(self.positions[att]) + gl.glDisableVertexAttribArray(self.positions[att]) + gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0) def unload(self): gl.glUseProgram(0) - gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0) def delete(self):