diff --git a/FWGL.hs b/FWGL.hs
--- a/FWGL.hs
+++ b/FWGL.hs
@@ -1,8 +1,8 @@
 {-|
     The main module. You should also import a backend:
 
-        * "FWGL.Backend.JavaScript": GHCJS/WebGL backend
-        * "FWGL.Backend.GLFW.GL20": GLFW/OpenGL 2.0 backend
+        * FWGL.Backend.JavaScript: GHCJS/WebGL backend (contained in fwgl-javascript)
+        * FWGL.Backend.GLFW.GL20: GLFW/OpenGL 2.0 backend (contained in fwgl-glfw)
         * FWGL.Backend.GLFW.GLES20: GLFW/OpenGL ES 2.0 backend (WIP)
 
 
diff --git a/FWGL/Geometry.hs b/FWGL/Geometry.hs
--- a/FWGL/Geometry.hs
+++ b/FWGL/Geometry.hs
@@ -41,7 +41,7 @@
         AttrListCons :: (H.Hashable c, AttributeCPU c g)
                      => g -> [c] -> AttrList gs -> AttrList (g ': gs)
 
--- ^ A set of attributes and indices.
+-- | A set of attributes and indices.
 data Geometry (is :: [*]) = Geometry (AttrList is) [Word16] Int
 
 data GPUGeometry = GPUGeometry {
@@ -50,10 +50,10 @@
         elementCount :: Int
 }
 
--- ^ A 3D geometry.
+-- | A 3D geometry.
 type Geometry3 = '[Position3, D3.UV, Normal3]
 
--- ^ A 2D geometry.
+-- | A 2D geometry.
 type Geometry2 = '[Position2, D2.UV]
 
 instance H.Hashable (AttrList is) where
diff --git a/FWGL/Graphics/Custom.hs b/FWGL/Graphics/Custom.hs
--- a/FWGL/Graphics/Custom.hs
+++ b/FWGL/Graphics/Custom.hs
@@ -18,6 +18,7 @@
         globalTexture,
         globalTexSize,
         layer,
+        subLayer,
         unsafeJoin,
         mkGeometry,
         mkTexture,
@@ -88,3 +89,11 @@
 -- | Generate a 1x1 texture.
 colorTex :: GLES => Color -> Texture
 colorTex c = mkTexture 1 1 [ c ]
+
+-- | Use a 'Layer' as a 'Texture' on another.
+subLayer :: Int                         -- ^ Texture width.
+         -> Int                         -- ^ Texture height.
+         -> Layer                       -- ^ Layer to draw on a 'Texture'.
+         -> (Texture -> [Layer])        -- ^ Layer to draw on the screen.
+         -> Layer
+subLayer = SubLayer
diff --git a/FWGL/Graphics/D2.hs b/FWGL/Graphics/D2.hs
--- a/FWGL/Graphics/D2.hs
+++ b/FWGL/Graphics/D2.hs
@@ -36,6 +36,9 @@
         -- ** Object layers
         layer,
         layerPrg,
+        program,
+        -- * Sublayers
+        C.subLayer,
         -- * Custom 2D objects
         Object,
         object,
@@ -70,7 +73,7 @@
 import FWGL.Graphics.Color
 import FWGL.Graphics.Draw
 import FWGL.Graphics.Shapes
-import FWGL.Graphics.Types
+import FWGL.Graphics.Types hiding (program)
 import FWGL.Graphics.Texture
 import FWGL.Internal.TList
 import FWGL.Shader.Default2D (Image, Depth, Transform2, View2)
diff --git a/FWGL/Graphics/D3.hs b/FWGL/Graphics/D3.hs
--- a/FWGL/Graphics/D3.hs
+++ b/FWGL/Graphics/D3.hs
@@ -16,7 +16,6 @@
         Texture,
         textureURL,
         textureFile,
-        textureLayer,
         C.colorTex,
         mkTexture,
         -- * Transformations
@@ -37,6 +36,9 @@
         -- ** Object layers
         layer,
         layerPrg,
+        program,
+        -- ** Sublayers
+        C.subLayer,
         -- * Custom 3D objects
         Object,
         object,
@@ -58,6 +60,7 @@
         mul4,
         -- ** View matrices
         perspectiveMat4,
+        cameraMat4,
         -- ** Transformation matrices
         idMat4,
         transMat4,
@@ -78,7 +81,7 @@
 import FWGL.Graphics.Types
 import FWGL.Internal.TList
 import FWGL.Shader.Default3D (Texture2, Transform3, View3)
-import FWGL.Shader.Program
+import FWGL.Shader.Program hiding (program)
 import FWGL.Graphics.Texture
 import FWGL.Vector
 
diff --git a/FWGL/Graphics/Draw.hs b/FWGL/Graphics/Draw.hs
--- a/FWGL/Graphics/Draw.hs
+++ b/FWGL/Graphics/Draw.hs
@@ -41,6 +41,8 @@
 
 drawInit :: (BackendIO, GLES) => Int -> Int -> GL DrawState
 drawInit w h = do enable gl_DEPTH_TEST
+                  enable gl_BLEND
+                  blendFunc gl_SRC_ALPHA gl_ONE_MINUS_SRC_ALPHA
                   clearColor 0.0 0.0 0.0 1.0
                   depthFunc gl_LESS
                   resize w h
@@ -49,8 +51,7 @@
                                    , programs = newGLResMap
                                    , gpuMeshes = newGLResMap
                                    , uniforms = newGLResMap
-                                   , textureImages = newGLResMap
-                                   , textureLayers = [] }
+                                   , textureImages = newGLResMap }
         where newGLResMap :: (Hashable i, Resource i r GL) => ResMap i r
               newGLResMap = newResMap
 
@@ -64,10 +65,16 @@
 drawBegin = gl . clear $ gl_COLOR_BUFFER_BIT .|. gl_DEPTH_BUFFER_BIT
 
 drawEnd :: GLES => Draw ()
-drawEnd = Draw get >>= mapM_ (gl . deleteTexture) . textureLayers
+drawEnd = return ()
 
 drawLayer :: (GLES, BackendIO) => Layer -> Draw ()
 drawLayer (Layer prg obj) = setProgram prg >> drawObject obj
+drawLayer (SubLayer w' h' sub sup) =
+        do t <- renderTexture w h sub
+           mapM_ drawLayer $ sup (TextureLoaded $ LoadedTexture w h t)
+           gl $ deleteTexture t
+        where w = fromIntegral w'
+              h = fromIntegral h'
 
 drawObject :: (GLES, BackendIO) => Object gs is -> Draw ()
 drawObject ObjectEmpty = return ()
@@ -131,8 +138,7 @@
 getGPUGeometry = getDrawResource gl gpuMeshes (\ m s -> s { gpuMeshes = m })
 
 getTexture :: (GLES, BackendIO) => Texture -> Draw (ResStatus LoadedTexture)
-getTexture (TextureLayer l w h) = do t <- renderTexture w h l
-                                     return . Loaded $ LoadedTexture w h t
+getTexture (TextureLoaded l) = return $ Loaded l
 getTexture (TextureImage t) = getTextureImage t
 
 getTextureImage :: (GLES, BackendIO) => TextureImage
@@ -143,25 +149,30 @@
 getProgram :: GLES => Program '[] '[] -> Draw (ResStatus LoadedProgram)
 getProgram = getDrawResource gl programs (\ m s -> s { programs = m })
 
-renderTexture :: GLES => GLSize -> GLSize -> Layer -> Draw GL.Texture
+renderTexture :: (GLES, BackendIO) => GLSize -> GLSize
+              -> Layer -> Draw GL.Texture
 renderTexture w h layer = do
-        t <- gl $ do fb <- createFramebuffer
+        fb <- gl createFramebuffer
+        t <- gl emptyTexture
 
-                     t <- emptyTexture
-                     arr <- liftIO $ noArray
-                     bindTexture gl_TEXTURE_2D t
-                     texImage2DBuffer gl_TEXTURE_2D 0 (fromIntegral gl_RGBA) w 
-                                      h 0 gl_RGBA
-                                      gl_UNSIGNED_BYTE arr
+        gl $ do arr <- liftIO $ noArray
+                bindTexture gl_TEXTURE_2D t
+                texImage2DBuffer gl_TEXTURE_2D 0 (fromIntegral gl_RGBA) w 
+                                 h 0 gl_RGBA
+                                 gl_UNSIGNED_BYTE arr
 
-                     bindFramebuffer gl_FRAMEBUFFER fb
-                     framebufferTexture2D gl_FRAMEBUFFER
-                                          gl_COLOR_ATTACHMENT0
-                                          gl_TEXTURE_2D t 0
-                     deleteFramebuffer fb
+                bindFramebuffer gl_FRAMEBUFFER fb
+                framebufferTexture2D gl_FRAMEBUFFER
+                                     gl_COLOR_ATTACHMENT0
+                                     gl_TEXTURE_2D t 0
+                -- viewport ?
 
-                     return t
-        Draw . modify $ \s -> s { textureLayers = t : textureLayers s }
+        drawBegin
+        drawLayer layer
+        drawEnd
+
+        gl $ deleteFramebuffer fb
+
         return t
 
 getDrawResource :: (Resource i r m, Hashable i)
diff --git a/FWGL/Graphics/Texture.hs b/FWGL/Graphics/Texture.hs
--- a/FWGL/Graphics/Texture.hs
+++ b/FWGL/Graphics/Texture.hs
@@ -4,7 +4,6 @@
         mkTexture,
         textureURL,
         textureFile,
-        textureLayer,
         textureHash,
         emptyTexture
 ) where
@@ -28,18 +27,14 @@
 mkTexture w h ps = TextureImage . TexturePixels ps (fromIntegral w)
                                                    (fromIntegral h) $ hash ps
 
--- | Creates a 'Texture' from an URL (JavaScript only).
+-- | Creates a 'Texture' from an URL or a local file.
 textureURL :: String  -- ^ URL
            -> Texture
 textureURL url = TextureImage . TextureURL url $ hash url
 
--- | Creates a 'Texture' from a file (Desktop only).
+-- | The same as 'textureURL'.
 textureFile :: String -> Texture
 textureFile = textureURL
-
--- | Creates a 'Texture' from a 'Layer'.
-textureLayer :: GLES => Int -> Int -> Layer -> Texture
-textureLayer w h l = TextureLayer l (fromIntegral w) (fromIntegral h)
 
 textureHash :: TextureImage -> Int
 textureHash (TexturePixels _ _ _ h) = h
diff --git a/FWGL/Graphics/Types.hs b/FWGL/Graphics/Types.hs
--- a/FWGL/Graphics/Types.hs
+++ b/FWGL/Graphics/Types.hs
@@ -37,8 +37,7 @@
         programs :: ResMap (Program '[] '[]) LoadedProgram,
         uniforms :: ResMap (LoadedProgram, String) UniformLocation,
         gpuMeshes :: ResMap (Geometry '[]) GPUGeometry,
-        textureImages :: ResMap TextureImage LoadedTexture,
-        textureLayers :: [GL.Texture]
+        textureImages :: ResMap TextureImage LoadedTexture
 }
 
 newtype Draw a = Draw { unDraw :: StateT DrawState GL a }
@@ -46,7 +45,7 @@
 
 -- | A texture.
 data Texture = TextureImage TextureImage
-             | TextureLayer Layer GLSize GLSize
+             | TextureLoaded LoadedTexture
              
 data TextureImage = TexturePixels [Color] GLSize GLSize Int
                   | TextureURL String Int
@@ -82,3 +81,4 @@
 -- | An object associated with a program.
 data Layer = forall oi pi og pg. (Subset oi pi, Subset og pg)
                               => Layer (Program pg pi) (Object og oi)
+           | SubLayer Int Int Layer (Texture -> [Layer])
diff --git a/FWGL/Utils.hs b/FWGL/Utils.hs
--- a/FWGL/Utils.hs
+++ b/FWGL/Utils.hs
@@ -1,6 +1,7 @@
 module FWGL.Utils (
         screenScale,
-        perspective4
+        perspective4,
+        perspectiveView
 ) where
 
 import FRP.Yampa
@@ -23,6 +24,15 @@
 perspective4 f n fov =
         size >>^ \(w, h) -> perspectiveMat4 f n fov
                                             (fromIntegral w / fromIntegral h)
+
+-- | Combine a perspective and a view matrix.
+perspectiveView :: Float    -- ^ Far
+                -> Float    -- ^ Near
+                -> Float    -- ^ FOV
+                -> SF (Input, M4) M4
+perspectiveView far near fov  =
+        perspective4 far near fov *** identity
+        >>^ \(perspMat, viewMat) -> mul4 viewMat perspMat
 
 -- | Like 'dynamic', but instead of comparing the two objects it checks the
 -- event with the new object.
diff --git a/FWGL/Vector.hs b/FWGL/Vector.hs
--- a/FWGL/Vector.hs
+++ b/FWGL/Vector.hs
@@ -8,6 +8,7 @@
         vec2,
         vec3,
         vec4,
+        dot4,
         mat2,
         mat3,
         mul3,
@@ -22,6 +23,8 @@
         rotAAMat4,
         scaleMat4,
         perspectiveMat4,
+        cameraMat4,
+        -- lookAtMat4,
         idMat3,
         transMat3,
         rotMat3,
@@ -97,6 +100,14 @@
 vec4 :: (Float, Float, Float, Float) -> V4
 vec4 (x, y, z, w) = V4 x y z w
 
+-- | 3D vector dot product.
+dot3 :: V3 -> V3 -> Float
+dot3 (V3 x y z) (V3 x' y' z') = x * x' + y * y' + z * z'
+
+-- | 4D vector dot product.
+dot4 :: V4 -> V4 -> Float
+dot4 (V4 x y z w) (V4 x' y' z' w') = x * x' + y * y' + z * z' + w * w'
+
 -- | Create a 2x2 matrix.
 mat2 :: ( Float, Float
         , Float, Float ) -> M2
@@ -261,6 +272,26 @@
              , 0      , 0 , (f + n) / (n - f) , (2 * f * n) / (n - f)
              , 0      , 0 , - 1               , 0)
         where s = 1 / tan (fov * pi / 360)
+
+-- | 4x4 FPS camera matrix.
+cameraMat4 :: V3        -- ^ Eye
+           -> Float     -- ^ Pitch
+           -> Float     -- ^ Yaw
+           -> M4
+cameraMat4 eye pitch yaw =
+        mat4 ( xx, yx, zx, 0
+             , xy, yy, zy, 0
+             , xz, yz, zz, 0
+             , - dot3 xv eye, - dot3 yv eye, - dot3 zv eye, 1)
+        where cosPitch = cos pitch
+              sinPitch = sin pitch
+              cosYaw = cos yaw
+              sinYaw = sin yaw
+              xv@(V3 xx xy xz) = V3 cosYaw 0 $ -sinYaw
+              yv@(V3 yx yy yz) = V3 (sinYaw * sinPitch) cosPitch $
+                                    cosYaw * sinPitch
+              zv@(V3 zx zy zz) = V3 (sinYaw * cosPitch) (-sinPitch) $
+                                    cosPitch * cosYaw
 
 -- | Quaternion to 4x4 matrix.
 quatToMat4 :: V4 -> M4
diff --git a/fwgl.cabal b/fwgl.cabal
--- a/fwgl.cabal
+++ b/fwgl.cabal
@@ -1,5 +1,5 @@
 name:                fwgl
-version:             0.1.0.2
+version:             0.1.0.3
 synopsis:            FRP 2D/3D game engine
 description:         FRP 2D/3D game engine (work in progress).
 homepage:            https://github.com/ZioCrocifisso/FWGL
