diff --git a/fsl/fslview/gl/globject.py b/fsl/fslview/gl/globject.py
index 5c0d1ced5b5b0c935eabadcba3a01460ca8bda60..88e10133759c808c69bdf4634cfd79c9a5a6ae29 100644
--- a/fsl/fslview/gl/globject.py
+++ b/fsl/fslview/gl/globject.py
@@ -14,6 +14,9 @@ OpenGL representation.
 """
 
 
+import numpy as np
+
+
 def createGLObject(image, display):
     """Create :class:`GLObject` instance for the given
     :class:`~fsl.data.image.Image` instance.
@@ -69,7 +72,7 @@ class GLObject(object):
         self.__updateListeners[name] = listener
 
         
-    def removeUpdateListener(self, name, listener):
+    def removeUpdateListener(self, name):
         """Removes a listener previously registered via
         :meth:`addUpdateListener`.
         """
@@ -225,10 +228,20 @@ class GLImageObject(GLObject):
 
 
     def getDataResolution(self, xax, yax):
+
+        image   = self.image
+        display = self.display
+        res     = display.resolution 
+        
+        if display.transform in ('id', 'pixdim'):
+
+            pixdim = np.array(image.pixdim[:3])
+            steps  = [res, res, res] / pixdim
+            res    = image.shape[:3] / steps
+            
+            return np.array(res.round(), dtype=np.uint32)
         
-        if self.display.transform in ('id', 'pixdim'):
-            return self.image.shape[:3]
         else:
-            lo, hi = self.display.getDisplayBounds()
-            minres = int(round(((hi - lo) / self.display.resolution).min()))
+            lo, hi = display.getDisplayBounds()
+            minres = int(round(((hi - lo) / res).min()))
             return [minres] * 3
diff --git a/fsl/fslview/gl/glvolume.py b/fsl/fslview/gl/glvolume.py
index 2efee28a5de2d73c4cb70d87bb104f7eaaffed1c..55800ec6818f96ed3f1a56ed1ad90368ffe654fc 100644
--- a/fsl/fslview/gl/glvolume.py
+++ b/fsl/fslview/gl/glvolume.py
@@ -258,6 +258,10 @@ class GLVolume(globject.GLImageObject):
             fslgl.glvolume_funcs.updateShaderState(self)
             self.onUpdate()
 
+        def update(*a):
+            self.onUpdate()
+
+        display.addListener('resolution',    lName, update)
         display.addListener('interpolation', lName, shaderUpdate)
         display.addListener('softwareMode',  lName, shaderCompile)
         display.addListener('alpha',         lName, colourUpdate)
@@ -277,6 +281,7 @@ class GLVolume(globject.GLImageObject):
 
         lName = self.name
 
+        display.removeListener('resolution',    lName)
         display.removeListener('interpolation', lName)
         display.removeListener('softwareMode',  lName)
         display.removeListener('alpha',         lName)
diff --git a/fsl/fslview/gl/routines.py b/fsl/fslview/gl/routines.py
index 86a3d01f483d41d1dcb2aa0c262d7dbcef72c724..6b1ff056212090eec1300706456304b1b87d4e27 100644
--- a/fsl/fslview/gl/routines.py
+++ b/fsl/fslview/gl/routines.py
@@ -461,8 +461,11 @@ def subsample(data, resolution, pixdim=None, volume=None):
     if pixdim is None:
         pixdim = (1.0, 1.0, 1.0)
 
+    if volume is None:
+        volume = slice(None, None, None)
+
     xstep = np.round(resolution / pixdim[0])
-    ystep = np.round(resolution / pixdim[1])
+    ystep = np.round(resolution / pixdim[1]) 
     zstep = np.round(resolution / pixdim[2])
 
     if xstep < 1: xstep = 1
@@ -472,23 +475,14 @@ def subsample(data, resolution, pixdim=None, volume=None):
     xstart = np.floor(xstep / 2)
     ystart = np.floor(ystep / 2)
     zstart = np.floor(zstep / 2)
-
-    if volume is not None:
-        if len(data.shape) > 3: sample = data[xstart::xstep,
-                                              ystart::ystep,
-                                              zstart::zstep,
-                                              volume]
-        else:                   sample = data[xstart::xstep,
-                                              ystart::ystep,
-                                              zstart::zstep]
-    else:
-        if len(data.shape) > 3: sample = data[xstart::xstep,
-                                              ystart::ystep,
-                                              zstart::zstep,
-                                              :]
-        else:                   sample = data[xstart::xstep,
-                                              ystart::ystep,
-                                              zstart::zstep]        
+        
+    if len(data.shape) > 3: sample = data[xstart::xstep,
+                                          ystart::ystep,
+                                          zstart::zstep,
+                                          volume]
+    else:                   sample = data[xstart::xstep,
+                                          ystart::ystep,
+                                          zstart::zstep]
 
     return sample, (xstart, ystart, zstart), (xstep, ystep, zstep)
 
diff --git a/fsl/fslview/gl/slicecanvas.py b/fsl/fslview/gl/slicecanvas.py
index 82a838fdacf85e65b4ae3def3c98131afa1554b3..f645a4e0d1eb6c3a2ea8d39ddd53583f33c96f96 100644
--- a/fsl/fslview/gl/slicecanvas.py
+++ b/fsl/fslview/gl/slicecanvas.py
@@ -382,12 +382,10 @@ class SliceCanvas(props.HasProperties):
             # by a RenderTexture object.
             if self.renderMode == 'offscreen':
                 
-                display = self.displayCtx.getDisplayProperties(image)
-                name    = '{}_{}_{}'.format(image.name, self.xax, self.yax)
-                rt      = textures.ImageRenderTexture(
+                name = '{}_{}_{}'.format(image.name, self.xax, self.yax)
+                rt   = textures.GLObjectRenderTexture(
                     name,
-                    image,
-                    display,
+                    globj,
                     self.xax,
                     self.yax)
 
@@ -968,7 +966,7 @@ class SliceCanvas(props.HasProperties):
         # those off-screen textures are all rendered on
         # to the screen canvas.
         if self.renderMode == 'offscreen':
-            textures.ImageRenderTexture.unbindAsRenderTarget()
+            textures.GLObjectRenderTexture.unbindAsRenderTarget()
             self._setViewport()
             self._drawOffscreenTextures() 
 
diff --git a/fsl/fslview/gl/textures/__init__.py b/fsl/fslview/gl/textures/__init__.py
index 7aaae3c8cf736acb887216127378e7eff0217ddb..a10bec9ac935815a9a1cb983b6339d76dcaebcd5 100644
--- a/fsl/fslview/gl/textures/__init__.py
+++ b/fsl/fslview/gl/textures/__init__.py
@@ -21,5 +21,5 @@ from imagetexture       import ImageTexture
 from colourmaptexture   import ColourMapTexture
 from selectiontexture   import SelectionTexture
 from rendertexture      import RenderTexture
-from rendertexture      import ImageRenderTexture
+from rendertexture      import GLObjectRenderTexture
 from rendertexturestack import RenderTextureStack
diff --git a/fsl/fslview/gl/textures/rendertexture.py b/fsl/fslview/gl/textures/rendertexture.py
index 29d5aa72e0648ff5e41ba7f61174a4f4aa88a30e..fe216b85f59d95cc84bb22e622e165d316c26710 100644
--- a/fsl/fslview/gl/textures/rendertexture.py
+++ b/fsl/fslview/gl/textures/rendertexture.py
@@ -11,8 +11,6 @@ import OpenGL.GL                        as gl
 import OpenGL.raw.GL._types             as gltypes
 import OpenGL.GL.EXT.framebuffer_object as glfbo
 
-import numpy                            as np
-
 import                            texture
 import fsl.fslview.gl.routines as glroutines
 
@@ -101,41 +99,24 @@ class RenderTexture(texture.Texture2D):
         self.unbindAsRenderTarget()
         self.unbindTexture()
 
-
-class ImageRenderTexture(RenderTexture):
-    """A :class:`RenderTexture` for off-screen volumetric rendering of an
-    :class:`.Image` instance.
-    """
+        
+class GLObjectRenderTexture(RenderTexture):
     
-    def __init__(self, name, image, display, xax, yax, maxResolution=512):
+    def __init__(self, name, globj, xax, yax, maxResolution=1024):
         """
         """
         
-        self.__image         = image
-        self.__display       = display
+        self.__globj         = globj
         self.__xax           = xax
         self.__yax           = yax
         self.__maxResolution = maxResolution
 
         RenderTexture.__init__(self, name)
 
-        self.__addListeners()        
-        self.__updateSize()
-
-
-    def __addListeners(self):
-
-        def onInterp(*a):
-            if self.__display.interpolation == 'none': interp = gl.GL_NEAREST
-            else:                                      interp = gl.GL_LINEAR
-            self.setInterpolation(interp)
-
         name = '{}_{}'.format(self.getTextureName(), id(self))
+        globj.addUpdateListener(name, self.__updateSize)
 
-        self.__display.addListener('imageType',     name, self.__updateSize)
-        self.__display.addListener('resolution',    name, self.__updateSize)
-        self.__display.addListener('interpolation', name, onInterp)
-        self.__display.addListener('transform',     name, self.__updateSize)
+        self.__updateSize()        
 
     
     def setAxes(self, xax, yax):
@@ -147,12 +128,8 @@ class ImageRenderTexture(RenderTexture):
     def destroy(self):
 
         name = '{}_{}'.format(self.getTextureName(), id(self))
-        
+        self.__globj.removeUpdateListener(name) 
         RenderTexture.destroy(self)
-        self.__display.removeListener('imageType',     name)
-        self.__display.removeListener('resolution',    name)
-        self.__display.removeListener('interpolation', name)
-        self.__display.removeListener('transform',     name)
 
     
     def setSize(self, width, height):
@@ -162,50 +139,15 @@ class ImageRenderTexture(RenderTexture):
         
         
     def __updateSize(self, *a):
-        image      = self.__image
-        display    = self.__display
-        maxRes     = self.__maxResolution
-
-        resolution = display.resolution / np.array(image.pixdim)
-        resolution = np.round(resolution)
-        keepAspectRatio = True
-
-        if resolution[0] < 1: resolution[0] = 1
-        if resolution[1] < 1: resolution[1] = 1
-        if resolution[2] < 1: resolution[2] = 1
-
-        # For some image types, the display resolution
-        # does not affect performance, and needs to be
-        # higher than the image resolution
-        if display.imageType == 'linevector':
-
-            keepAspectRatio = False
-            width  = 16 * image.shape[self.__xax] / resolution[self.__xax]
-            height = 16 * image.shape[self.__yax] / resolution[self.__yax]
-        
-        # If the display transformation is 'id' or
-        # 'pixdim', then the display coordinate system
-        # axes line up with the voxel coordinate system
-        # axes, so we can just match the voxel resolution        
-        elif display.transform in ('id', 'pixdim'):
-            
-            width  = image.shape[self.__xax] / resolution[self.__xax]
-            height = image.shape[self.__yax] / resolution[self.__yax]
-
-        # However, if we're displaying in world coordinates,
-        # we cannot assume any correspondence between the
-        # voxel coordinate system and the display coordinate
-        # system. So we'll use a fixed size render texture
-        # instead.
-        elif display.transform == 'affine':
-            width  = maxRes / resolution.min()
-            height = maxRes / resolution.min()
-
-        # Limit the width/height to an arbitrary maximum
-        if not keepAspectRatio:
-            if width  > maxRes: width  = maxRes
-            if height > maxRes: height = maxRes
-        elif width > maxRes or height > maxRes:
+        globj  = self.__globj
+        maxRes = self.__maxResolution
+
+        resolution = globj.getDataResolution(self.__xax, self.__yax)
+
+        width  = resolution[self.__xax]
+        height = resolution[self.__yax]
+
+        if width > maxRes or height > maxRes:
             oldWidth, oldHeight = width, height
             ratio = min(width, height) / max(width, height)
             
@@ -216,11 +158,15 @@ class ImageRenderTexture(RenderTexture):
                 height = maxRes
                 width  = height * ratio
 
-            log.debug('Limiting texture resolution to {}x{} '
-                      '(for image resolution {}x{})'.format(
-                          *map(int, (width, height, oldWidth, oldHeight))))
-
-        width  = int(round(width))
-        height = int(round(height))
+            width  = int(round(width))
+            height = int(round(height))
 
-        RenderTexture.setSize(self, width, height)
+            log.debug('Limiting texture resolution to {}x{} '
+                      '(for {} resolution {}x{})'.format(
+                          width,
+                          height,
+                          type(globj).__name__,
+                          oldWidth,
+                          oldHeight))
+
+        RenderTexture.setSize(self, width, height) 
diff --git a/fsl/fslview/gl/textures/texture.py b/fsl/fslview/gl/textures/texture.py
index 9117a32a3c6436642eab2ff98235e4f3e4c9d7eb..0fac58404796aba126c27375f311d5c2b263c9dd 100644
--- a/fsl/fslview/gl/textures/texture.py
+++ b/fsl/fslview/gl/textures/texture.py
@@ -169,6 +169,12 @@ class Texture2D(Texture):
             print data.shape, data.dtype
             data = data.ravel('F')
 
+        log.debug('Configuring {} ({}) with size {}x{}'.format(
+            type(self).__name__,
+            self.getTextureHandle(),
+            self.__width,
+            self.__height))
+
         # If the width and height have not changed,
         # then we don't need to re-define the texture.
         if self.__width  == self.__oldWidth  and \