diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.4.1
+
+- Fixed the `sizeOf` implementatiof of `a :. b`.
+- Added `nubDirect`, which can be used to turn *direct geometry* into *indirect geometry*.
+
 # 0.4
 
 #### Non-breaking changes
diff --git a/luminance.cabal b/luminance.cabal
--- a/luminance.cabal
+++ b/luminance.cabal
@@ -1,5 +1,5 @@
 name:                luminance
-version:             0.4
+version:             0.4.1
 synopsis:            Type-safe, dependently-typed and stateless graphics framework
 description:         This package exposes several modules to work with /GPUs/ in a stateless and
                      type-safe way. Currently, it uses __OpenGL__ as backend hardware technology but
@@ -112,7 +112,9 @@
                      , UndecidableInstances
 
   build-depends:       base           >= 4.8  && < 4.9
+                     , containers     >= 0.5  && < 0.6
                      , contravariant  >= 1.3  && < 1.4
+                     , dlist          >= 0.7  && < 0.8
                      , gl             >= 0.7  && < 0.8
                      , linear         >= 1.20 && < 1.21
                      , mtl            >= 2.2  && < 2.3
diff --git a/src/Graphics/Luminance/Core/Geometry.hs b/src/Graphics/Luminance/Core/Geometry.hs
--- a/src/Graphics/Luminance/Core/Geometry.hs
+++ b/src/Graphics/Luminance/Core/Geometry.hs
@@ -12,6 +12,9 @@
 
 import Control.Monad.IO.Class ( MonadIO(..) )
 import Control.Monad.Trans.Resource ( MonadResource, register )
+import Data.DList as DL ( empty, snoc )
+import Data.Foldable ( toList )
+import Data.Map as M ( empty, insert, lookup, size )
 import Data.Proxy ( Proxy(..) )
 import Data.Word ( Word32 )
 import Foreign.Marshal.Alloc ( alloca )
@@ -95,3 +98,18 @@
     vertNb = length vertices
     ixNb   = length indices
     mode'  = fromGeometryMode mode
+
+-- |/O (n log n)/
+--
+-- Turn /direct geometry data/ into /indirect data/. This function removes duplicate vertices from
+-- the data you pass in and registers indices in consequence.
+nubDirect :: (Foldable f,Ord a,Integral i) => f a -> ([a],[i])
+nubDirect dvertices = (toList uvertices,toList indices)
+  where
+    (uvertices,indices,_) = foldl rmDup (DL.empty,DL.empty,M.empty) dvertices
+    rmDup (uverts,inds,seen) v =
+      case M.lookup v seen of
+        Just i -> (uverts,inds `snoc` i,seen)
+        Nothing ->
+          let s = fromIntegral (size seen)
+          in (uverts `snoc` v,inds `snoc` s,insert v s seen)
diff --git a/src/Graphics/Luminance/Core/Tuple.hs b/src/Graphics/Luminance/Core/Tuple.hs
--- a/src/Graphics/Luminance/Core/Tuple.hs
+++ b/src/Graphics/Luminance/Core/Tuple.hs
@@ -21,7 +21,7 @@
 infixr 6 :.
 
 instance (Storable a,Storable b) => Storable (a :. b) where
-  sizeOf (a :. b) = sizeOf a + sizeOf b
+  sizeOf _ = sizeOf (undefined :: a) + sizeOf (undefined :: b)
   alignment _ = 4 -- packed data
   peek p = do
     a <- peek $ castPtr p
diff --git a/src/Graphics/Luminance/Geometry.hs b/src/Graphics/Luminance/Geometry.hs
--- a/src/Graphics/Luminance/Geometry.hs
+++ b/src/Graphics/Luminance/Geometry.hs
@@ -13,6 +13,7 @@
     Geometry
   , GeometryMode(..)
   , createGeometry
+  , nubDirect
   ) where
 
 import Graphics.Luminance.Core.Geometry
