diff --git a/all.lua b/all.lua
index 3834ea8af129a952137c66671170349b14bb4b72..1ad8f371e6959a5df8927cad158e9b648fb64167 100644
--- a/all.lua
+++ b/all.lua
@@ -3,3 +3,4 @@ require("kara3d.matrix")
 require("kara3d.quaternion")
 require("kara3d.transform")
 require("kara3d.shape")
+require("kara3d.light")
diff --git a/light.lua b/light.lua
new file mode 100644
index 0000000000000000000000000000000000000000..2dce32a647d040c7cba52f079953062ccc8a3c98
--- /dev/null
+++ b/light.lua
@@ -0,0 +1,24 @@
+require("kara3d.vector")
+require("kara3d.matrix")
+require("kara3d.quaternion")
+require("kara3d.transform")
+require("utils")
+
+
+light = {class = "light"}
+light.__index = light
+
+
+-- Creates a new light with transform t and RGB value diff and spec
+function light.new(t, diff, spec)
+  local l = {transform = t, diffuse = diff or {255, 255, 255}, specular = spec or {255, 255, 255}}
+  setmetatable(l, light)
+  return l
+end
+
+
+
+-- Clones this light
+function light:clone()
+  return light.new(self.transform, table.copy(self.diffuse), table.copy(self.specular))
+end
\ No newline at end of file
diff --git a/shape.lua b/shape.lua
index 64ef73cf6cb85d972ce2bf855c8332aee960c4ea..8043306f1018ffdcbb36b8562dbe1a2c666dbc86 100644
--- a/shape.lua
+++ b/shape.lua
@@ -2,6 +2,7 @@ require("kara3d.vector")
 require("kara3d.matrix")
 require("kara3d.quaternion")
 require("kara3d.transform")
+require("kara3d.lights")
 require("utils")
 re = require("re")
 
@@ -13,13 +14,22 @@ shape.__index = shape
 face = {class = "face"}
 face.__index = face
 
--- Creates a new shape with transform t and faces f
-function shape.new(t, f)
-  local s = {transform = t, faces = f or {}}
-  setmetatable(s, shape)
-  return s
+material = {class = "material"}
+material.__index = material
+
+
+
+function material.new(a, d, sp, sh)
+  local m = {ambient = a or vector.new(3, {1, 1, 1}), 
+            diffuse = d or vector.new(3, {1, 1, 1}),
+            specular = sp or vector.new(3, {1, 1, 1}),
+            shininess = sh or 1}
+  setmetatable(m, material)
+  return m
 end
 
+
+
 -- Creates a new face with vertices c, normal n and tags t
 function face.new(v, n, t)
   local f = {vertices = v or {}, normal = n or -vector.cardinal(3, 3), tags = t}
@@ -27,6 +37,51 @@ function face.new(v, n, t)
   return f
 end
 
+function face:mean()
+  sum = vector.zero(3)
+  for i = 1, #self.vertices do
+    sum = sum + self.vertices[i]
+  end
+  return (1/(#self.vertices)) * sum
+end
+
+
+function face:shade(mat, lights, ambient)
+  local Ka = mat.ambient
+  local Kd = mat.diffuse
+  local Ks = mat.specular
+  local shine = mat.shininess
+  
+  local N = self.normal:normalized()
+  local P = self:mean():normalized()
+  local V = vector.new(3, {0, 0, -1})
+
+  local I = Ka * ambient
+
+  for i = 1, #lights do
+    local l = lights[i]
+    local L = (light.transform:position(true) - P):normalized()
+    local R = 2 * vector.dot(L, N) * N - L
+
+    -- Diffuse component
+    I = I + Kd * vector.dot(L, N) * l.diffuse
+
+    -- Specular component
+    I = I + Ks * math.pow(vector.dot(R, V), shine) * l.specular
+  end
+  
+  return I
+end
+
+
+-- Creates a new shape with transform t and faces f
+function shape.new(t, f)
+  local s = {transform = t, faces = f or {}}
+  setmetatable(s, shape)
+  return s
+end
+
+
 -- Clones this shape
 function shape:clone()
   return shape.new(self.transform, table.copy(self.faces))