diff --git a/Graphics/GL/Low.hs b/Graphics/GL/Low.hs
--- a/Graphics/GL/Low.hs
+++ b/Graphics/GL/Low.hs
@@ -70,7 +70,7 @@
   --   vbo <- newVBO blob StaticDraw
   --   bindVBO vbo
   --   -- connect program to vertex data via the VAO
-  --   setVertexAttributeLayout [Attrib "position" 2 VFloat]
+  --   setVertexLayout [Attrib "position" 2 GLFloat]
   --   return (vao, prog)
   -- 
   -- draw vao prog = do
@@ -159,7 +159,7 @@
   --
   -- After installing a program with 'useProgram' and binding a source VBO
   -- to the array buffer binding target ('bindVBO') then the bound VAO can be
-  -- updated ('setVertexAttributeLayout') with new vertex attribute information.
+  -- updated ('setVertexLayout') with new vertex attribute information.
   -- After this, the VBO can be rebound to configure a different set of inputs
   -- with a different source. Many VAOs can be created and swapped out to pipe
   -- vertex data in different ways to different programs (or the same program).
@@ -327,10 +327,9 @@
 
   -- ** Vertex Attributes
   -- | See also "Graphics.GL.Low.VertexAttrib"
-  setVertexAttributeLayout,
-  VertexAttributeLayout(..),
-  LayoutElement(..),
-  ComponentFormat(..),
+  setVertexLayout,
+  VertexLayout(..),
+  DataType(..),
 
 
   -- * Textures
diff --git a/Graphics/GL/Low/Blending.hs b/Graphics/GL/Low/Blending.hs
--- a/Graphics/GL/Low/Blending.hs
+++ b/Graphics/GL/Low/Blending.hs
@@ -60,7 +60,7 @@
 --         , -0.5, -0.5 ] :: V.Vector Float
 --   vbo <- newVBO blob StaticDraw
 --   bindVBO vbo
---   setVertexAttributeLayout [Attrib "position" 2 VFloat]
+--   setVertexLayout [Attrib "position" 2 GLFloat]
 --   enableBlending basicBlending
 --   return (vao, prog)
 -- 
diff --git a/Graphics/GL/Low/Shader.hs b/Graphics/GL/Low/Shader.hs
--- a/Graphics/GL/Low/Shader.hs
+++ b/Graphics/GL/Low/Shader.hs
@@ -78,9 +78,9 @@
 --         ,  0.4, -0.4, 1, 1] :: V.Vector Float
 --   vbo <- newVBO blob StaticDraw
 --   bindVBO vbo
---   setVertexAttributeLayout
---     [ Attrib "position" 2 VFloat
---     , Attrib "location" 2 VFloat ]
+--   setVertexLayout
+--     [ Attrib "position" 2 GLFloat
+--     , Attrib "location" 2 GLFloat ]
 --   return (vao, prog1, prog2, prog3)
 -- 
 -- draw vao prog1 prog2 prog3 t = do
diff --git a/Graphics/GL/Low/VAO.hs b/Graphics/GL/Low/VAO.hs
--- a/Graphics/GL/Low/VAO.hs
+++ b/Graphics/GL/Low/VAO.hs
@@ -12,7 +12,7 @@
 -- - Bind a VAO
 -- - Bind a VBO
 -- - Use a Program
--- - call 'Graphics.GL.Low.VertexAttrib.setVertexAttributeLayout' which will
+-- - call 'Graphics.GL.Low.VertexAttrib.setVertexLayout' which will
 -- lookup the position of the input variables and issue the appropriate
 -- glVertexAttribPointer calls.
 --
diff --git a/Graphics/GL/Low/VertexAttrib.hs b/Graphics/GL/Low/VertexAttrib.hs
--- a/Graphics/GL/Low/VertexAttrib.hs
+++ b/Graphics/GL/Low/VertexAttrib.hs
@@ -1,6 +1,30 @@
--- | Vertex Attribute Array.
-module Graphics.GL.Low.VertexAttrib where
+-- | To feed vertices into the vertex shader, the layout of a vertex must be
+-- specified in the current VAO for the current shader program. Make a list of
+-- LayoutElements and use 'setVertexLayout' on it as seen below.
+--
+-- == Example
+--
+-- @
+-- setVertexLayout
+--   [ Attrib "position"  3 GLFloat   -- first 12 bytes maps to: in vec3 position;
+--   , Attrib "shininess" 1 GLFloat   -- next 4 bytes maps to:   in float shininess;
+--   , Attrib "texcoord"  2 GLFloat   -- next 8 bytes maps to:   in vec2 texcoord;
+--   , Unused 2                       -- next 2 bytes ignored
+--   , Attrib "seed"      1 GLShort ] -- next 2 bytes read as 16-bit signed int
+--                                    --   and mapped to: in float seed;
+-- @
+--
+-- In this example four mappings from the current VBO to the variables
+-- in the current Program will be established in the current VAO.
 
+
+module Graphics.GL.Low.VertexAttrib (
+  setVertexLayout,
+  VertexLayout(..),
+  DataType(..)
+) where
+
+
 import Foreign.C.String
 import Foreign.Ptr
 import Foreign.Marshal
@@ -8,106 +32,33 @@
 import Control.Monad (forM_)
 
 import Graphics.GL
-
 import Graphics.GL.Low.Classes
 
 -- | The name of a vertex input to a program combined with the
 -- component format and number of components for that attribute in the
 -- vertex data. Alternatively the size of an unused section of the data
 -- in bytes.
-data LayoutElement =
-  Attrib String Int ComponentFormat | -- ^ Name, component count and component format of a vertex attribute.
+data VertexLayout =
+  Attrib String Int DataType | -- ^ Name, component count and component format of a vertex attribute.
   Unused Int -- ^ Size in bytes of an unused section of the vertex data.
     deriving Show
 
--- | The layout of interleaved vertex attribute data.
-type VertexAttributeLayout = [LayoutElement]
-
 -- | The size and interpretation of a vertex attribute component. Normalized
 -- components will be mapped to floats in the range [0, 1].
-data ComponentFormat =
-  VFloat | -- ^ 4-byte float
-  VByte | 
-  VUByte | 
-  VByteNormalized | 
-  VUByteNormalized |
-  VShort | -- ^ 2-byte signed integer
-  VUShort | -- ^ 2-byte unsigned integer
-  VShortNormalized |
-  VUShortNormalized |
-  VInt | -- ^ 4-byte signed integer
-  VUInt | -- ^ 4-byte unsigned integer
-  VIntNormalized |
-  VUIntNormalized
+data DataType =
+  GLFloat         | -- ^ 4-byte float
+  GLUnsignedByte  | -- ^ unsigned byte
+  GLByte          | -- ^ signed byte
+  GLShort         | -- ^ 2-byte signed integer
+  GLUnsignedShort | -- ^ 2-byte unsigned integer
+  GLInt           | -- ^ 4-byte signed integer
+  GLUnsignedInt     -- ^ 4-byte unsigned integer
     deriving (Eq, Show)
 
-instance ToGL ComponentFormat where
-  toGL VFloat = GL_FLOAT
-  toGL VByte = GL_BYTE
-  toGL VUByte = GL_UNSIGNED_BYTE
-  toGL VByteNormalized = GL_BYTE
-  toGL VUByteNormalized = GL_UNSIGNED_BYTE
-  toGL VShort = GL_SHORT
-  toGL VUShort = GL_UNSIGNED_SHORT
-  toGL VShortNormalized = GL_SHORT
-  toGL VUShortNormalized = GL_UNSIGNED_SHORT
-  toGL VInt = GL_INT
-  toGL VUInt = GL_UNSIGNED_INT
-  toGL VIntNormalized = GL_INT
-  toGL VUIntNormalized = GL_UNSIGNED_INT
-  
-
-
-elaborateLayout :: Int -> VertexAttributeLayout -> [(String, Int, Int, ComponentFormat)]
-elaborateLayout here layout = case layout of
-  [] -> []
-  (Unused n):xs -> elaborateLayout (here+n) xs
-  (Attrib name n fmt):xs ->
-    let size = n * sizeOfVertexComponent fmt in
-    (name, n, here, fmt) : elaborateLayout (here+size) xs
-
-totalLayout :: VertexAttributeLayout -> Int
-totalLayout layout = sum (map arraySize layout) where
-  arraySize (Unused n) = n
-  arraySize (Attrib _ n fmt) = n * sizeOfVertexComponent fmt
-
-sizeOfVertexComponent :: ComponentFormat -> Int
-sizeOfVertexComponent c = case c of
-  VByte -> 1
-  VUByte -> 1
-  VByteNormalized -> 1
-  VUByteNormalized -> 1
-  VShort -> 2
-  VUShort -> 2
-  VShortNormalized -> 2
-  VUShortNormalized -> 2
-  VInt -> 4
-  VUInt -> 4
-  VIntNormalized -> 4
-  VUIntNormalized -> 4
-  VFloat -> 4
-
-isNormalized :: ComponentFormat -> Bool
-isNormalized c = case c of
-  VByte -> False
-  VUByte -> False
-  VByteNormalized -> True
-  VUByteNormalized -> True
-  VShort -> False
-  VUShort -> False
-  VShortNormalized -> True
-  VUShortNormalized -> True
-  VInt -> False
-  VUInt -> False
-  VIntNormalized -> True
-  VUIntNormalized -> True
-  VFloat -> False
-
-
 -- | This configures the currently bound VAO. It calls glVertexAttribPointer
 -- and glEnableVertexAttribArray.
-setVertexAttributeLayout :: VertexAttributeLayout -> IO ()
-setVertexAttributeLayout layout = do
+setVertexLayout :: [VertexLayout] -> IO ()
+setVertexLayout layout = do
   p <- alloca (\ptr -> glGetIntegerv GL_CURRENT_PROGRAM ptr >> peek ptr)
   if p == 0
     then return ()
@@ -116,18 +67,49 @@
       let total = totalLayout layout
       forM_ layout' $ \(name, size, offset, fmt) -> do
         attrib <- withCString name $ \ptr -> glGetAttribLocation (fromIntegral p) (castPtr ptr)
-        --let stride = total - size * sizeOfVertexComponent fmt
         let stride = total
-        let norm = isNormalized fmt
         glVertexAttribPointer
           (fromIntegral attrib)
           (fromIntegral size)
           (toGL fmt)
-          (toGL norm)
+          GL_FALSE
           (fromIntegral stride)
           (castPtr (nullPtr `plusPtr` offset))
         glEnableVertexAttribArray (fromIntegral attrib)
 
+
+instance ToGL DataType where
+  toGL GLFloat         = GL_FLOAT
+  toGL GLByte          = GL_BYTE
+  toGL GLUnsignedByte  = GL_UNSIGNED_BYTE
+  toGL GLShort         = GL_SHORT
+  toGL GLUnsignedShort = GL_UNSIGNED_SHORT
+  toGL GLInt           = GL_INT
+  toGL GLUnsignedInt   = GL_UNSIGNED_INT
+
 instance ToGL Bool where
   toGL True = GL_TRUE
   toGL False = GL_FALSE
+
+elaborateLayout :: Int -> [VertexLayout] -> [(String, Int, Int, DataType)]
+elaborateLayout here layout = case layout of
+  [] -> []
+  (Unused n):xs -> elaborateLayout (here+n) xs
+  (Attrib name n ty):xs ->
+    let size = n * sizeOfType ty in
+    (name, n, here, ty) : elaborateLayout (here+size) xs
+
+totalLayout :: [VertexLayout] -> Int
+totalLayout layout = sum (map arraySize layout) where
+  arraySize (Unused n) = n
+  arraySize (Attrib _ n ty) = n * sizeOfType ty
+
+sizeOfType :: DataType -> Int
+sizeOfType c = case c of
+  GLFloat         -> 4
+  GLByte          -> 1
+  GLUnsignedByte  -> 1
+  GLShort         -> 2
+  GLUnsignedShort -> 2
+  GLInt           -> 4
+  GLUnsignedInt   -> 4
diff --git a/lowgl.cabal b/lowgl.cabal
--- a/lowgl.cabal
+++ b/lowgl.cabal
@@ -10,7 +10,7 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.2.1.1
+version:             0.3.0.0
 
 -- A short (one-line) description of the package.
 synopsis:            Basic gl wrapper and reference
@@ -89,4 +89,4 @@
 source-repository this
   type: git
   location: https://github.com/evanrinehart/lowgl
-  tag: 0.2.1.1
+  tag: 0.3.0.0
