diff --git a/fsl/fsleyes/gl/gl21/glmodel_funcs.py b/fsl/fsleyes/gl/gl21/glmodel_funcs.py
index 2092f73c3e6e44d4d596c1a170ecf014a9a000a8..97a5a3e4058fc69483ad5a951d35491e817302f4 100644
--- a/fsl/fsleyes/gl/gl21/glmodel_funcs.py
+++ b/fsl/fsleyes/gl/gl21/glmodel_funcs.py
@@ -8,10 +8,9 @@
 class to render :class:`.Model` overlays in an OpenGL 2.1 compatible manner.
 """
 
-import numpy                  as np
-import OpenGL.GL              as gl
 
-import fsl.fsleyes.gl.shaders as shaders
+import fsl.fsleyes.gl.shaders      as shaders
+import fsl.fsleyes.gl.glsl.program as glslprogram
 
 
 def compileShaders(self):
@@ -19,19 +18,22 @@ def compileShaders(self):
     instance. The shaders, and locations of uniform variables, are added
     as attributes of the instance.
     """
-    vertShaderSrc = shaders.getVertexShader(  self)
-    fragShaderSrc = shaders.getFragmentShader(self)
-    self.shaders  = shaders.compileShaders(vertShaderSrc, fragShaderSrc)
 
-    self.texPos    = gl.glGetUniformLocation(self.shaders, 'tex')
-    self.offsetPos = gl.glGetUniformLocation(self.shaders, 'offsets')
+    if self.shader is not None:
+        self.shader.delete()
+    
+    vertSrc = shaders.getVertexShader(  self)
+    fragSrc = shaders.getFragmentShader(self)
+
+    self.shader = glslprogram.ShaderProgram(vertSrc, fragSrc)
 
 
 def destroy(self):
     """Deletes the vertex/fragment shaders that were compiled by
     :func:`compileShaders`.
     """
-    gl.glDeleteProgram(self.shaders)
+    self.shader.delete()
+    self.shader = None
 
 
 def updateShaders(self):
@@ -48,19 +50,19 @@ def updateShaders(self):
     # width/height (whichever is smaller)
     outlineWidth *= 10
     offsets = 2 * [min(outlineWidth / width, outlineWidth / height)]
-    offsets = np.array(offsets, dtype=np.float32)
 
-    gl.glUseProgram(self.shaders)
-    gl.glUniform1i( self.texPos,    0)
-    gl.glUniform2fv(self.offsetPos, 1, offsets)
-    gl.glUseProgram(0)
+    self.shader.load()
+    self.shader.set('tex',     0)
+    self.shader.set('offsets', offsets)
+    self.shader.unload()
 
 
 def loadShaders(self):
     """Loads the :class:`.GLModel` vertex/fragment shaders. """
-    gl.glUseProgram(self.shaders)
+
+    self.shader.load()
 
 
 def unloadShaders(self):
     """Un-loads the :class:`.GLModel` vertex/fragment shaders. """
-    gl.glUseProgram(0)
+    self.shader.unload()
diff --git a/fsl/fsleyes/gl/glmodel.py b/fsl/fsleyes/gl/glmodel.py
index d0862c4e460a39a49b1d1345afe8c69a2a7349b0..e589abd2203378df245da2cd2067100334b2f3d5 100644
--- a/fsl/fsleyes/gl/glmodel.py
+++ b/fsl/fsleyes/gl/glmodel.py
@@ -76,6 +76,7 @@ class GLModel(globject.GLObject):
 
         globject.GLObject.__init__(self)
 
+        self.shader  = None
         self.overlay = overlay
         self.display = display
         self.opts    = display.getDisplayOpts()
diff --git a/fsl/fsleyes/gl/glsl/program.py b/fsl/fsleyes/gl/glsl/program.py
index a72d36a9d6b3331797e96e3df5a54495e88c9aa5..00cf7d3fd62f8f3c8183c0fbe3a440536d28b5f1 100644
--- a/fsl/fsleyes/gl/glsl/program.py
+++ b/fsl/fsleyes/gl/glsl/program.py
@@ -315,7 +315,7 @@ class ShaderProgram(object):
 
 
     def _uniform_vec2(self, pos, val):
-        gl.glUniform2fv(pos, np.array(val, dtype=np.float32))
+        gl.glUniform2fv(pos, 1, np.array(val, dtype=np.float32))
 
 
     def _uniform_vec3(self, pos, val):