From 40208b6a48a4c3ea92466e297d1f48c8583edb4d Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauld.mccarthy@gmail.com>
Date: Mon, 19 May 2014 14:12:40 +0100
Subject: [PATCH] God damn it, OpenGL gives me the shits. Looks like I have to
 make the dimensions of the 3D texture image all a power of two.

---
 fsl/fslview/slicecanvas.py | 54 ++++++++++++++++----------------------
 1 file changed, 23 insertions(+), 31 deletions(-)

diff --git a/fsl/fslview/slicecanvas.py b/fsl/fslview/slicecanvas.py
index 13ad485fd..169dc704e 100644
--- a/fsl/fslview/slicecanvas.py
+++ b/fsl/fslview/slicecanvas.py
@@ -56,8 +56,8 @@ class GLImageData(object):
           - canvas: The SliceCanvas object which is rendering the image.
         """
 
-        self.image          = image
-        self.canvas         = canvas
+        self.image      = image
+        self.canvas     = canvas
 
         # Here, x,y, and z refer to screen
         # coordinates, not image coordinates:
@@ -87,9 +87,10 @@ class GLImageData(object):
         object that was passed to the GLImageData constructor.
         """
 
-        image  = self.image
-        canvas = self.canvas
-        
+        image           = self.image
+        canvas          = self.canvas
+        self.dataBuffer = self.initImageBuffer()
+
         # Data stored in the geometry buffer. Defines
         # the geometry of a single voxel, rendered as
         # a triangle strip.
@@ -103,15 +104,13 @@ class GLImageData(object):
         # x/y/z coordinates are stored as
         # VBO arrays in the range [0, 1]
         voxData = []
-        for dim in image.shape:
+        for (imgDim, texDim) in zip(image.shape, self.imageTexShape):
 
-            step = 1.0 / dim
-            
-            data = np.arange(0.0 + step / 2,
-                             1.0 + step / 2,
-                             step,
-                             dtype=np.float32)
-            voxData.append(data)
+            stop = float(imgDim) / texDim
+            step = stop / imgDim
+            data = np.arange(step / 2.0, stop, step, dtype=np.float32)
+
+            voxData.append(data)        
         
         # the screen x coordinate data has to be repeated (ylen)
         # times - we are drawing row-wise, and opengl does not
@@ -150,24 +149,9 @@ class GLImageData(object):
         positionData = positionData.ravel('C')
 
         # The image buffers, containing the image data 
-        imageBuffer     = self.initImageBuffer()
         screenPosBuffer = vbo.VBO(positionData, gl.GL_STATIC_DRAW)
         geomBuffer      = vbo.VBO(geomData,     gl.GL_STATIC_DRAW)
 
-        print 
-        print 'xBuffer'
-        print xData
-        print 
-        print 'yBuffer'
-        print yData
-        print 
-        print 'zBuffer'
-        print zData
-        print
-        print 'posData'
-        print positionData
-
-        self.dataBuffer      = imageBuffer
         self.voxXBuffer      = xBuffer
         self.voxYBuffer      = yBuffer
         self.voxZBuffer      = zBuffer
@@ -189,6 +173,10 @@ class GLImageData(object):
 
         image = self.image
 
+        texShape = 2 ** (np.ceil(np.log2(image.shape)))
+        pad      = [(0, l - s) for (l, s) in zip(texShape, image.shape)]
+        self.imageTexShape = texShape 
+
         try:    imageBuffer = image.getAttribute('glBuffers')
         except: imageBuffer = None
 
@@ -200,6 +188,10 @@ class GLImageData(object):
         imageData = np.array(image.data, dtype=np.float32)
         imageData = 255.0 * (imageData       - imageData.min()) / \
                             (imageData.max() - imageData.min())
+
+        # and each dimension is padded so
+        # it has a power-of-two length
+        imageData = np.pad(imageData, pad, 'constant', constant_values=0)
         imageData = np.array(imageData, dtype=np.uint8)
 
         # Then flattened, with fortran dimension ordering,
@@ -224,9 +216,9 @@ class GLImageData(object):
         gl.glTexImage3D(gl.GL_TEXTURE_3D,
                         0,
                         arbrg.GL_R8,
-                        image.shape[0],
-                        image.shape[1],
-                        image.shape[2],
+                        texShape[0],
+                        texShape[1],
+                        texShape[2],
                         0,
                         gl.GL_RED,
                         gl.GL_UNSIGNED_BYTE,
-- 
GitLab