summary refs log tree commit diff
path: root/res/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'res/shaders')
-rw-r--r--res/shaders/colors.fs137
1 files changed, 114 insertions, 23 deletions
diff --git a/res/shaders/colors.fs b/res/shaders/colors.fs
index 228f555..d10e45a 100644
--- a/res/shaders/colors.fs
+++ b/res/shaders/colors.fs
@@ -14,6 +14,7 @@ struct Light {
   vec3 direction;
 
   float cutOff;
+  float outerCutOff;
 
   vec3 ambient;
   vec3 diffuse;
@@ -32,37 +33,127 @@ uniform vec3 view_position;
 uniform Material material;
 uniform Light light;
 
-void main() {
-  vec3 light_dir = normalize(light.position - FragPos);
 
-  float theta = dot(light_dir, normalize(-light.direction));
+struct DirLight {
+  vec3 direction;
 
-  if (theta > light.cutOff) {
-    // ambient
-    vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
+  vec3 ambient;
+  vec3 diffuse;
+  vec3 specular;
+};
+uniform DirLight dirLight;
 
-    // diffuse
-    vec3 norm = normalize(Normal);
-    float diff = max(dot(norm, light_dir), 0.0);
-    vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;
+struct PointLight {
+  vec3 position;
 
-    // specular
-    vec3 view_dir = normalize(view_position - FragPos);
-    vec3 reflect_dir = reflect(-light_dir, norm);
-    float spec = pow(max(dot(view_dir, reflect_dir), 0.0), material.shininess);
-    vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;
+  float constant;
+  float linear;
+  float quadratic;
 
-    float distance = length(light.position - FragPos);
-    float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
+  vec3 ambient;
+  vec3 diffuse;
+  vec3 specular;
+};
+#define NR_POINT_LIGHTS 4
+uniform PointLight pointLights[NR_POINT_LIGHTS];
 
-    diffuse *= attenuation;
-    specular *= attenuation;
+struct SpotLight {
+  vec3 position;
+  vec3 direction;
+
+  float cutOff;
+  float outerCutOff;
+
+  float constant;
+  float linear;
+  float quadratic;
+
+  vec3 ambient;
+  vec3 diffuse;
+  vec3 specular;
+};
+uniform SpotLight spotLight;
+
+vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
+vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
+vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
+
+void main()
+{
+  vec3 norm = normalize(Normal);
+  vec3 viewDir = normalize(view_position - FragPos);
+
+  vec3 result = CalcDirLight(dirLight, norm, viewDir);
 
-    vec3 result = ambient + diffuse + specular;
-    FragColor = vec4(result, 1.0);
-  } else {
-    FragColor = vec4(light.ambient * texture(material.diffuse, TexCoords).rgb, 1.0);
+  for (int i = 0; i < NR_POINT_LIGHTS; i++) {
+    result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
   }
 
+  result += CalcSpotLight(spotLight, norm, FragPos, viewDir);
 
+  FragColor = vec4(result, 1.0);
+}
+
+// calculates the color when using a directional light.
+vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
+{
+    vec3 lightDir = normalize(-light.direction);
+    // diffuse shading
+    float diff = max(dot(normal, lightDir), 0.0);
+    // specular shading
+    vec3 reflectDir = reflect(-lightDir, normal);
+    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
+    // combine results
+    vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
+    vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
+    vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
+    return (ambient + diffuse + specular);
+}
+
+// calculates the color when using a point light.
+vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
+{
+    vec3 lightDir = normalize(light.position - fragPos);
+    // diffuse shading
+    float diff = max(dot(normal, lightDir), 0.0);
+    // specular shading
+    vec3 reflectDir = reflect(-lightDir, normal);
+    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
+    // attenuation
+    float distance = length(light.position - fragPos);
+    float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
+    // combine results
+    vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
+    vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
+    vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
+    ambient *= attenuation;
+    diffuse *= attenuation;
+    specular *= attenuation;
+    return (ambient + diffuse + specular);
+}
+
+// calculates the color when using a spot light.
+vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
+{
+    vec3 lightDir = normalize(light.position - fragPos);
+    // diffuse shading
+    float diff = max(dot(normal, lightDir), 0.0);
+    // specular shading
+    vec3 reflectDir = reflect(-lightDir, normal);
+    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
+    // attenuation
+    float distance = length(light.position - fragPos);
+    float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
+    // spotlight intensity
+    float theta = dot(lightDir, normalize(-light.direction));
+    float epsilon = light.cutOff - light.outerCutOff;
+    float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
+    // combine results
+    vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
+    vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
+    vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
+    ambient *= attenuation * intensity;
+    diffuse *= attenuation * intensity;
+    specular *= attenuation * intensity;
+    return (ambient + diffuse + specular);
 }