diff --git a/shaders/frag.glsl b/shaders/frag.glsl
index b9a6c9e..3071b9d 100644
--- a/shaders/frag.glsl
+++ b/shaders/frag.glsl
@@ -1,27 +1,40 @@
 #version 330 core
 
+struct Material {
+  vec3 ambient;
+  vec3 diffuse;
+  vec3 specular;
+  float shininess;
+};
+
+struct Light {
+  vec3 position;
+  vec3 ambient;
+  vec3 diffuse;
+  vec3 specular;
+};
+
 in vec3 vert_normal;
 in vec3 frag_position;
 
 out vec4 color;
 
+uniform Material material;
+uniform Light light;
 uniform vec3 camera_position;
-uniform vec3 object_color;
-uniform vec3 light_color;
-uniform vec3 light_position;
 
 void main() {
   float ambient_strength   = 0.15;
   float specular_strength  = 0.5;
   vec3  normal             = normalize(vert_normal);
-  vec3  light_direction    = normalize(light_position - frag_position);
+  vec3  light_direction    = normalize(light.position - frag_position);
   vec3  view_direction     = normalize(camera_position - frag_position);
   vec3  reflect_direction  = reflect(-light_direction, normal);
   float diff               = max(dot(normal, light_direction), 0.0);
-  float spec               = pow(max(dot(reflect_direction, view_direction), 0.0), 32);
-  vec3  ambient            = light_color * ambient_strength;
-  vec3  diffuse            = diff * light_color;
-  vec3  specular           = specular_strength * spec * light_color;
+  float spec               = pow(max(dot(reflect_direction, view_direction), 0.0), material.shininess);
+  vec3  ambient            = light.ambient * material.ambient;
+  vec3  diffuse            = light.diffuse * (diff * material.diffuse);
+  vec3  specular           = light.specular * (spec * material.specular);
 
-  color = vec4(object_color * (ambient + diffuse + specular), 1.0);
+  color = vec4(ambient + diffuse + specular, 1.0);
 };
diff --git a/shaders/light_frag.glsl b/shaders/light_frag.glsl
index b460b8c..f0fbad8 100644
--- a/shaders/light_frag.glsl
+++ b/shaders/light_frag.glsl
@@ -2,6 +2,8 @@
 
 out vec4 color;
 
+uniform vec3 light_diffuse;
+
 void main() {
-  color = vec4(1.0);
+  color = vec4(light_diffuse, 1.0);
 }
diff --git a/src/main.cc b/src/main.cc
index 0d29f13..4b4e61a 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -32,6 +32,10 @@
 #define WINDOW_HALF_WIDTH  640
 #define WINDOW_HALF_HEIGHT 360
 
+#define min(a, b) (a < b ? a : b)
+#define max(a, b) (a > b ? a : b)
+#define clamp(v, a, b) (min(max(v, a), b))
+
 enum exit_codes : int {
   EXIT_CODE_SUCCESS,
   EXIT_CODE_SDL_INIT_FAILED,
@@ -168,14 +172,12 @@ int main() {
   Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"};
   Shader light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"};
 
-  main_shader.set_vec3("object_color", glm::vec3(1.0f, 0.5f, 0.31f));
-  main_shader.set_vec3("light_color", glm::vec3(1.0f, 1.0f, 1.0f));
-
   const float camera_speed   = 25.0f;
   glm::vec3 camera_position  = glm::vec3(-2.0f, 0.0f, 6.0f);
   glm::vec3 camera_forward   = glm::vec3(0.0f);
   glm::vec3 world_up         = glm::vec3(0.0f, 1.0f, 0.0f);
   glm::vec3 light_position   = glm::vec3(1.0f,  0.5f, 0.0f);
+  glm::vec3 light_diffuse    = glm::vec3(0.5f, 0.5f, 0.5f);
 
   float yaw   = -70.0f;
   float pitch = 0.0f;
@@ -185,7 +187,14 @@ int main() {
   glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 100.0f);
   glm::mat3 normal_mat = glm::mat3(1.0f);
 
-  main_shader.set_mat4("projection", projection);
+  main_shader.set_mat4 ("projection", projection);
+  main_shader.set_vec3 ("material.ambient", glm::vec3(1.0f, 0.5f, 0.31f));
+  main_shader.set_vec3 ("material.diffuse", glm::vec3(1.0f, 0.5f, 0.31f));
+  main_shader.set_vec3 ("material.specular", glm::vec3(0.5f, 0.5f, 0.5f));
+  main_shader.set_float("material.shininess", 32.0f);
+  main_shader.set_vec3 ("light.ambient", glm::vec3(0.2f, 0.2f, 0.2f));
+  main_shader.set_vec3 ("light.diffuse", light_diffuse);
+  main_shader.set_vec3 ("light.specular", glm::vec3(1.0f, 1.0f, 1.0f));
   light_shader.set_mat4("projection", projection);
 
   const float light_radius  = 3.0f;
@@ -202,6 +211,11 @@ int main() {
     float seconds  = ticks * 0.001f;
     delta          = (ticks - last_frame) * 0.001f;
     light_position = glm::vec3(sin(seconds) * light_radius, light_position.y, cos(seconds) * light_radius);
+    light_diffuse  = glm::vec3(
+                        clamp(sin(seconds * 3.0f) + 1.0f, 0.0f, 1.0f),
+                        clamp(cos(seconds * 8.0f) + 1.0f, 0.0f, 1.0f),
+                        clamp(tan(seconds * 5.0f) + 3.0f, 0.0f, 1.0f)
+                     );
     last_frame     = ticks;
 
     while (SDL_PollEvent(&event)) {
@@ -275,7 +289,8 @@ int main() {
     model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f,  0.0f,  0.0f));
     normal_mat = glm::transpose(glm::inverse(model));
     main_shader.activate();
-    main_shader.set_vec3("light_position", light_position);
+    main_shader.set_vec3("light.position", light_position);
+    main_shader.set_vec3("light.diffuse", light_diffuse);
     main_shader.set_mat4("model", model);
     main_shader.set_mat3("normal_mat", normal_mat);
     glBindVertexArray(vao);
@@ -285,6 +300,7 @@ int main() {
     model = glm::scale(model, glm::vec3(0.2f));
     light_shader.activate();
     light_shader.set_mat4("model", model);
+    light_shader.set_vec3("light_diffuse", light_diffuse);
     glBindVertexArray(light_vao);
     glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void *)0);