diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 ### 2.1.6
 
+- Runtime optimizations (Use BaseVertex for glDraw* instead of offsetting each attribute)
+
+### 2.1.6
+
 - Adding support for normal Floats, Int32s and Word32s in PrimitiveStreams
 - Runtime optimizations
 
diff --git a/GPipe.cabal b/GPipe.cabal
--- a/GPipe.cabal
+++ b/GPipe.cabal
@@ -1,5 +1,5 @@
 name:           GPipe
-version:        2.1.6
+version:        2.1.7
 cabal-version:  >= 1.8
 build-type:     Simple
 author:         Tobias Bexelius
diff --git a/src/Graphics/GPipe/Internal/PrimitiveArray.hs b/src/Graphics/GPipe/Internal/PrimitiveArray.hs
--- a/src/Graphics/GPipe/Internal/PrimitiveArray.hs
+++ b/src/Graphics/GPipe/Internal/PrimitiveArray.hs
@@ -13,80 +13,82 @@
 
 -- | A vertex array is the basic building block for a primitive array. It is created from the contents of a 'Buffer', but unlike a 'Buffer',
 --   it may be truncated, zipped with other vertex arrays, and even morphed into arrays of a different type with the provided 'Functor' instance.
---   A @VertexArray t a@ has elements of type @a@, and @t@ indicates whether the vertex array may be used as instances or not.   
-data VertexArray t a = VertexArray  { 
+--   A @VertexArray t a@ has elements of type @a@, and @t@ indicates whether the vertex array may be used as instances or not.
+data VertexArray t a = VertexArray  {
     -- | Retrieve the number of elements in a 'VertexArray'.
-    vertexArrayLength :: Int, 
-    bArrBFunc:: BInput -> a 
+    vertexArrayLength :: Int,
+    vertexArraySkip :: Int,
+    bArrBFunc:: BInput -> a
     }
 
--- | A phantom type to indicate that a 'VertexArray' may only be used for instances (in 'toPrimitiveArrayInstanced' and 'toPrimitiveArrayIndexedInstanced'). 
+-- | A phantom type to indicate that a 'VertexArray' may only be used for instances (in 'toPrimitiveArrayInstanced' and 'toPrimitiveArrayIndexedInstanced').
 data Instances
 
--- | Create a 'VertexArray' from a 'Buffer'. The vertex array will have the same number of elements as the buffer, use 'takeVertices' and 'dropVertices' to make it smaller. 
+-- | Create a 'VertexArray' from a 'Buffer'. The vertex array will have the same number of elements as the buffer, use 'takeVertices' and 'dropVertices' to make it smaller.
 newVertexArray :: Buffer os a -> Render os f (VertexArray t a)
-newVertexArray buffer = Render $ return $ VertexArray (bufferLength buffer) $ bufBElement buffer
+newVertexArray buffer = Render $ return $ VertexArray (bufferLength buffer) 0 $ bufBElement buffer
 
 instance Functor (VertexArray t) where
-    fmap f (VertexArray n g) = VertexArray n (f . g)
+    fmap f (VertexArray n s g) = VertexArray n s (f . g)
 
 -- | Zip two 'VertexArray's using the function given as first argument. If either of the argument 'VertexArray's are restriced to 'Instances' only, then so will the resulting
 --   array be, as depicted by the 'Combine' type family.
-zipVertices :: (a -> b -> c) -> VertexArray t a -> VertexArray t' b -> VertexArray (Combine t t') c 
-zipVertices h (VertexArray n f) (VertexArray m g) = VertexArray (min n m) (\x -> h (f x) (g x))
+zipVertices :: (a -> b -> c) -> VertexArray t a -> VertexArray t' b -> VertexArray (Combine t t') c
+zipVertices h (VertexArray n s f) (VertexArray m t g) = VertexArray (min n m) totSkip newArrFun
+    where totSkip = min s t
+          newArrFun x = let baseSkip = bInSkipElems x - totSkip in h (f x { bInSkipElems = baseSkip + s}) (g x { bInSkipElems = baseSkip + t})
 
 type family Combine t t' where
-    Combine () Instances = Instances 
-    Combine Instances () = Instances 
-    Combine Instances Instances = Instances 
-    Combine () () = () 
+    Combine () Instances = Instances
+    Combine Instances () = Instances
+    Combine Instances Instances = Instances
+    Combine () () = ()
 
 -- | @takeVertices n a@ creates a shorter vertex array by taking the @n@ first elements of the array @a@.
 takeVertices :: Int -> VertexArray t a -> VertexArray t a
-takeVertices n (VertexArray l f) = VertexArray (min (max n 0) l) f
+takeVertices n (VertexArray l s f) = VertexArray (min (max n 0) l) s f
 
 -- | @dropVertices n a@ creates a shorter vertex array by dropping the @n@ first elements of the array @a@. The argument array @a@ must not be
 --   constrained to only 'Instances'.
 dropVertices :: Int -> VertexArray () a -> VertexArray t a
-dropVertices n (VertexArray l f) = VertexArray (l - n') g
+dropVertices n (VertexArray l s f) = VertexArray (l - n') (s+n') f
         where
             n' = min (max n 0) l
-            g bIn = f $ bIn { bInSkipElems = bInSkipElems bIn + n'}
 
 -- | @replicateEach n a@ will create a longer vertex array, only to be used for instances, by replicating each element of the array @a@ @n@ times. E.g.
---   @replicateEach 3 {ABCD...}@ will yield @{AAABBBCCCDDD...}@. This is particulary useful before zipping the array with another that has a different replication rate.  
+--   @replicateEach 3 {ABCD...}@ will yield @{AAABBBCCCDDD...}@. This is particulary useful before zipping the array with another that has a different replication rate.
 replicateEach :: Int -> VertexArray t a -> VertexArray Instances a
-replicateEach n (VertexArray m f) = VertexArray (n*m) (\x -> f $ x {bInInstanceDiv = bInInstanceDiv x * n})
+replicateEach n (VertexArray m s f) = VertexArray (n*m) s (\x -> f $ x {bInInstanceDiv = bInInstanceDiv x * n})
 
 type family IndexFormat a where
-    IndexFormat (B Word32) = Word32 
-    IndexFormat (BPacked Word16) = Word16 
-    IndexFormat (BPacked Word8) = Word8 
+    IndexFormat (B Word32) = Word32
+    IndexFormat (BPacked Word16) = Word16
+    IndexFormat (BPacked Word8) = Word8
 
 -- | An index array is like a vertex array, but contains only integer indices. These indices must come from a tightly packed 'Buffer', hence the lack of
 --   a 'Functor' instance and no conversion from 'VertexArray's.
-data IndexArray = IndexArray { 
-    iArrName :: IORef GLuint, 
+data IndexArray = IndexArray {
+    iArrName :: IORef GLuint,
     -- | Numer of indices in an 'IndexArray'.
-    indexArrayLength:: Int, 
-    offset:: Int, 
-    restart:: Maybe Int, 
-    indexType :: GLuint 
-    } 
+    indexArrayLength:: Int,
+    offset:: Int,
+    restart:: Maybe Int,
+    indexType :: GLuint
+    }
 
 -- | Create an 'IndexArray' from a 'Buffer' of unsigned integers (as constrained by the closed 'IndexFormat' type family instances). The index array will have the same number of elements as the buffer, use 'takeIndices' and 'dropIndices' to make it smaller.
---   The @Maybe a@ argument is used to optionally denote a primitive restart index. 
+--   The @Maybe a@ argument is used to optionally denote a primitive restart index.
 newIndexArray :: forall os f b a. (BufferFormat b, Integral a, IndexFormat b ~ a) => Buffer os b -> Maybe a -> Render os f IndexArray
-newIndexArray buf r = let a = undefined :: b in Render $ return $ IndexArray (bufName buf) (bufferLength buf) 0 (fmap fromIntegral r) (getGlType a) 
- 
+newIndexArray buf r = let a = undefined :: b in Render $ return $ IndexArray (bufName buf) (bufferLength buf) 0 (fmap fromIntegral r) (getGlType a)
+
 -- | @takeIndices n a@ creates a shorter index array by taking the @n@ first indices of the array @a@.
 takeIndices :: Int -> IndexArray -> IndexArray
 takeIndices n i = i { indexArrayLength = min (max n 0) (indexArrayLength i) }
 
 -- | @dropIndices n a@ creates a shorter index array by dropping the @n@ first indices of the array @a@.
 dropIndices :: Int -> IndexArray -> IndexArray
-dropIndices n i = i { indexArrayLength = l - n', offset = offset i + n' } 
-    where 
+dropIndices n i = i { indexArrayLength = l - n', offset = offset i + n' }
+    where
         l = indexArrayLength i
         n' = min (max n 0) l
 
@@ -102,7 +104,7 @@
     LineStrip :: PrimitiveTopology Lines
     LineLoop :: PrimitiveTopology Lines
     PointList :: PrimitiveTopology Points
-    
+
 toGLtopology :: PrimitiveTopology p -> GLuint
 toGLtopology TriangleList = GL_TRIANGLES
 toGLtopology TriangleStrip = GL_TRIANGLE_STRIP
@@ -111,8 +113,8 @@
 toGLtopology LineStrip = GL_LINE_STRIP
 toGLtopology LineLoop = GL_LINE_LOOP
 toGLtopology PointList = GL_POINTS
-  
 
+
 {-
 Some day:
 
@@ -127,11 +129,12 @@
 -}
 
 type InstanceCount = Int
+type BaseVertex = Int
 
-data PrimitiveArrayInt p a = PrimitiveArraySimple (PrimitiveTopology p) Int a 
-                           | PrimitiveArrayIndexed (PrimitiveTopology p) IndexArray a 
-                           | PrimitiveArrayInstanced (PrimitiveTopology p) InstanceCount Int a 
-                           | PrimitiveArrayIndexedInstanced (PrimitiveTopology p) IndexArray InstanceCount a 
+data PrimitiveArrayInt p a = PrimitiveArraySimple (PrimitiveTopology p) Int BaseVertex a
+                           | PrimitiveArrayIndexed (PrimitiveTopology p) IndexArray BaseVertex a
+                           | PrimitiveArrayInstanced (PrimitiveTopology p) InstanceCount Int BaseVertex a
+                           | PrimitiveArrayIndexedInstanced (PrimitiveTopology p) IndexArray InstanceCount BaseVertex a
 
 -- | An array of primitives
 newtype PrimitiveArray p a = PrimitiveArray {getPrimitiveArray :: [PrimitiveArrayInt p a]}
@@ -142,16 +145,16 @@
 
 instance Functor (PrimitiveArray p) where
     fmap f (PrimitiveArray xs) = PrimitiveArray  $ fmap g xs
-        where g (PrimitiveArraySimple p l a) = PrimitiveArraySimple p l (f a)
-              g (PrimitiveArrayIndexed p i a) = PrimitiveArrayIndexed p i (f a)
-              g (PrimitiveArrayInstanced p il l a) = PrimitiveArrayInstanced p il l (f a)
-              g (PrimitiveArrayIndexedInstanced p i il a) = PrimitiveArrayIndexedInstanced p i il (f a)
-              
+        where g (PrimitiveArraySimple p l s a) = PrimitiveArraySimple p l s (f a)
+              g (PrimitiveArrayIndexed p i s a) = PrimitiveArrayIndexed p i s (f a)
+              g (PrimitiveArrayInstanced p il l s a) = PrimitiveArrayInstanced p il l s (f a)
+              g (PrimitiveArrayIndexedInstanced p i il s a) = PrimitiveArrayIndexedInstanced p i il s (f a)
+
 toPrimitiveArray :: PrimitiveTopology p -> VertexArray () a -> PrimitiveArray p a
-toPrimitiveArray p va = PrimitiveArray [PrimitiveArraySimple p (vertexArrayLength va) (bArrBFunc va (BInput 0 0))]
+toPrimitiveArray p va = PrimitiveArray [PrimitiveArraySimple p (vertexArrayLength va) (vertexArraySkip va) (bArrBFunc va (BInput 0 0))]
 toPrimitiveArrayIndexed :: PrimitiveTopology p -> IndexArray -> VertexArray () a -> PrimitiveArray p a
-toPrimitiveArrayIndexed p ia va = PrimitiveArray [PrimitiveArrayIndexed p ia (bArrBFunc va (BInput 0 0))]
+toPrimitiveArrayIndexed p ia va = PrimitiveArray [PrimitiveArrayIndexed p ia (vertexArraySkip va) (bArrBFunc va (BInput 0 0))]
 toPrimitiveArrayInstanced :: PrimitiveTopology p -> (a -> b -> c) -> VertexArray () a -> VertexArray t b -> PrimitiveArray p c
-toPrimitiveArrayInstanced p f va ina = PrimitiveArray [PrimitiveArrayInstanced p (vertexArrayLength ina) (vertexArrayLength va) (f (bArrBFunc va $ BInput 0 0) (bArrBFunc ina $ BInput 0 1))]
+toPrimitiveArrayInstanced p f va ina = PrimitiveArray [PrimitiveArrayInstanced p (vertexArrayLength ina) (vertexArrayLength va) (vertexArraySkip va) (f (bArrBFunc va $ BInput 0 0) (bArrBFunc ina $ BInput (vertexArraySkip ina) 1))] -- Base instance not supported in GL < 4, so need to burn in
 toPrimitiveArrayIndexedInstanced :: PrimitiveTopology p -> IndexArray -> (a -> b -> c) -> VertexArray () a -> VertexArray t b -> PrimitiveArray p c
-toPrimitiveArrayIndexedInstanced p ia f va ina = PrimitiveArray [PrimitiveArrayIndexedInstanced p ia (vertexArrayLength ina) (f (bArrBFunc va $ BInput 0 0) (bArrBFunc ina $ BInput 0 1))]
+toPrimitiveArrayIndexedInstanced p ia f va ina = PrimitiveArray [PrimitiveArrayIndexedInstanced p ia (vertexArrayLength ina) (vertexArraySkip va) (f (bArrBFunc va $ BInput 0 0) (bArrBFunc ina $ BInput (vertexArraySkip ina) 1))] -- Base instance not supported in GL < 4, so need to burn in
diff --git a/src/Graphics/GPipe/Internal/PrimitiveStream.hs b/src/Graphics/GPipe/Internal/PrimitiveStream.hs
--- a/src/Graphics/GPipe/Internal/PrimitiveStream.hs
+++ b/src/Graphics/GPipe/Internal/PrimitiveStream.hs
@@ -94,14 +94,14 @@
                                    return $ PrimitiveStream [(x, (Nothing, PrimitiveStreamData n uSize))]
     where
         ToVertex (Kleisli uWriter) (Kleisli mf) (Kleisli bindingm) = toVertex :: ToVertex a (VertexFormat a)
-        drawcall (PrimitiveArraySimple p l a) binds = (attribs a binds, glDrawArrays (toGLtopology p) 0 (fromIntegral l))
-        drawcall (PrimitiveArrayIndexed p i a) binds = (attribs a binds, do
+        drawcall (PrimitiveArraySimple p l s a) binds = (attribs a binds, glDrawArrays (toGLtopology p) (fromIntegral s) (fromIntegral l))
+        drawcall (PrimitiveArrayIndexed p i s a) binds = (attribs a binds, do
                                                     bindIndexBuffer i
-                                                    glDrawElements (toGLtopology p) (fromIntegral $ indexArrayLength i) (indexType i) (intPtrToPtr $ fromIntegral $ offset i * glSizeOf (indexType i)))
-        drawcall (PrimitiveArrayInstanced p il l a) binds = (attribs a binds, glDrawArraysInstanced (toGLtopology p) 0 (fromIntegral l) (fromIntegral il))
-        drawcall (PrimitiveArrayIndexedInstanced p i il a) binds = (attribs a binds, do
+                                                    glDrawElementsBaseVertex (toGLtopology p) (fromIntegral $ indexArrayLength i) (indexType i) (intPtrToPtr $ fromIntegral $ offset i * glSizeOf (indexType i)) (fromIntegral s))
+        drawcall (PrimitiveArrayInstanced p il l s a) binds = (attribs a binds, glDrawArraysInstanced (toGLtopology p) (fromIntegral s) (fromIntegral l) (fromIntegral il))
+        drawcall (PrimitiveArrayIndexedInstanced p i il s a) binds = (attribs a binds, do
                                                       bindIndexBuffer i
-                                                      glDrawElementsInstanced (toGLtopology p) (fromIntegral $ indexArrayLength i) (indexType i) (intPtrToPtr $ fromIntegral $ offset i * glSizeOf (indexType i)) (fromIntegral il))
+                                                      glDrawElementsInstancedBaseVertex (toGLtopology p) (fromIntegral $ indexArrayLength i) (indexType i) (intPtrToPtr $ fromIntegral $ offset i * glSizeOf (indexType i)) (fromIntegral il) (fromIntegral s))
         bindIndexBuffer i = do case restart i of Just x -> do glEnable GL_PRIMITIVE_RESTART
                                                               glPrimitiveRestartIndex (fromIntegral x)
                                                  Nothing -> glDisable GL_PRIMITIVE_RESTART
