diff --git a/fsl/fsleyes/displaycontext/vectoropts.py b/fsl/fsleyes/displaycontext/vectoropts.py
index a9eace48153bce99dcc61d08503bfcaaacd6677c..079182e5dada1d6ff3cd8a8427892ff32027ed7a 100644
--- a/fsl/fsleyes/displaycontext/vectoropts.py
+++ b/fsl/fsleyes/displaycontext/vectoropts.py
@@ -123,10 +123,12 @@ class VectorOpts(volumeopts.ImageOpts):
             if not isinstance(overlay, fslimage.Image):
                 continue
 
-            # an image can only be used to modulate
-            # the vector image if it shares the same
-            # dimensions as said vector image
-            if overlay.shape != self.overlay.shape[:3]:
+            # an image can only be used to
+            # modulate the vector image if
+            # it shares the same dimensions
+            # as said vector image. 4D
+            # images are ok though.
+            if overlay.shape[:3] != self.overlay.shape[:3]:
                 continue
 
             modOptions.append(overlay)
diff --git a/fsl/fsleyes/gl/glvector.py b/fsl/fsleyes/gl/glvector.py
index 886cfd75f3f78e28d04f02a411926302826c7692..5a8ea15b39d51535b7b80261261eaf3352ef88c3 100644
--- a/fsl/fsleyes/gl/glvector.py
+++ b/fsl/fsleyes/gl/glvector.py
@@ -87,6 +87,7 @@ class GLVector(globject.GLImageObject):
         self.xColourTexture = textures.ColourMapTexture('{}_x'.format(name))
         self.yColourTexture = textures.ColourMapTexture('{}_y'.format(name))
         self.zColourTexture = textures.ColourMapTexture('{}_z'.format(name))
+        self.modImage       = None
         self.modTexture     = None
         self.imageTexture   = None
         self.prefilter      = prefilter
@@ -110,10 +111,12 @@ class GLVector(globject.GLImageObject):
         glresources.delete(self.imageTexture.getTextureName())
         glresources.delete(self.modTexture  .getTextureName())
 
+        self.removeListeners()
+        self.deregisterModulateImage()
+
         self.imageTexture = None
         self.modTexture   = None
-
-        self.removeListeners()
+        self.modImage     = None
 
         globject.GLImageObject.destroy(self)
 
@@ -132,6 +135,8 @@ class GLVector(globject.GLImageObject):
             self.onUpdate()
         
         def modUpdate( *a):
+            self.deregisterModulateImage()
+            self.registerModulateImage() 
             self.refreshModulateTexture()
             self.updateShaderState()
             self.onUpdate()
@@ -266,7 +271,49 @@ class GLVector(globject.GLImageObject):
         raise NotImplementedError('updateShaderState must be implemented by '
                                   '{} subclasses'.format(type(self).__name__))
 
+
+    def registerModulateImage(self):
+        """Called when the :attr:`.VectorOpts.modulate` property changes.
+        Registers a listener with the :attr:`.ImageOpts.volume` property
+        of the modulate image, so the modulate texture can be updated when
+        the image volume changes.
+        """
+        
+        modImage = self.displayOpts.modulate
+        
+        if modImage is None or modImage == 'none': self.modImage = None
+        else:                                      self.modImage = modImage
+        
+        if self.modImage is None:
+            return
+
+        modOpts = self.displayOpts.displayCtx.getOpts(modImage) 
+
+        def volumeChange(*a):
+            
+            self.modTexture.set(volume=modOpts.volume)
+            self.refreshModulateTexture()
+            self.onUpdate()
+
+        modOpts.addListener('volume', self.name, volumeChange, weak=False) 
+
     
+    def deregisterModulateImage(self):
+        """Called when the :attr:`.VectorOpts.modulate` property changes.
+        Deregisters the :attr:`.ImageOpts.volume` listener that was
+        registered in :meth:`registerModulateImage`.
+        """ 
+
+        if self.modImage is None:
+            return
+
+        modOpts = self.displayOpts.displayCtx.getOpts(self.modImage) 
+
+        modOpts.removeListener('volume', self.name)
+
+        self.modImage = None
+
+            
     def refreshModulateTexture(self):
         """Called when the :attr`.VectorOpts.modulate` property changes.