130 lines
3.3 KiB
GLSL
130 lines
3.3 KiB
GLSL
#version 460 core
|
|
|
|
in vec4 vertex_color;
|
|
in vec2 texture_coord;
|
|
in vec3 normal;
|
|
in vec3 frag_pos;
|
|
|
|
out vec4 color;
|
|
|
|
// Must match the same as in math.h
|
|
const int MAX_POINT_LIGHTS = 3;
|
|
const int MAX_SPOT_LIGHTS = 3;
|
|
|
|
struct Light {
|
|
vec3 color;
|
|
float ambient_intensity;
|
|
float diffuse_intensity;
|
|
};
|
|
|
|
struct Directional_Light {
|
|
Light light;
|
|
vec3 direction;
|
|
};
|
|
|
|
struct Point_Light {
|
|
Light light;
|
|
vec3 position;
|
|
float constant;
|
|
float linear;
|
|
float exponent;
|
|
};
|
|
|
|
struct Spot_Light {
|
|
Point_Light point_light;
|
|
|
|
vec3 direction;
|
|
float edge;
|
|
};
|
|
|
|
struct Material {
|
|
float shininess;
|
|
float specular_intensity;
|
|
};
|
|
|
|
|
|
uniform Directional_Light sun;
|
|
uniform Point_Light point_lights[MAX_POINT_LIGHTS];
|
|
uniform Spot_Light spot_lights[MAX_SPOT_LIGHTS];
|
|
|
|
uniform int point_light_count;
|
|
uniform int spot_light_count;
|
|
uniform sampler2D tex;
|
|
uniform Material material;
|
|
uniform vec3 eye_position;
|
|
|
|
vec4 calculate_light_by_direction(Light light, vec3 direction) {
|
|
vec4 ambient_color = vec4(light.color, 1.0f) * light.ambient_intensity;
|
|
|
|
float diffuse_factor = max(dot(normalize(normal), normalize(direction)), 0.0f);
|
|
vec4 diffuse_color = vec4(light.color * light.diffuse_intensity * diffuse_factor, 1.0f);
|
|
|
|
vec4 specular_color = vec4(0, 0, 0, 0);
|
|
|
|
if (diffuse_factor > 0.0f) {
|
|
vec3 frag_to_eye = normalize(eye_position - frag_pos);
|
|
vec3 reflected_vertex = normalize(reflect(direction, normalize(normal)));
|
|
float specular_factor = dot(frag_to_eye, reflected_vertex);
|
|
|
|
if (specular_factor > 0.0f) {
|
|
specular_factor = pow(specular_factor, material.shininess);
|
|
specular_color = vec4(light.color * material.specular_intensity * specular_factor, 1.0f);
|
|
}
|
|
}
|
|
|
|
return ambient_color + diffuse_color + specular_color;
|
|
}
|
|
|
|
vec4 calculate_point_light(Point_Light point_light) {
|
|
vec3 direction = frag_pos - point_light.position;
|
|
float distance = length(direction);
|
|
direction = normalize(direction);
|
|
|
|
vec4 light_color = calculate_light_by_direction(point_light.light, direction);
|
|
float attentuation = point_light.exponent * distance * distance + point_light.linear * distance + point_light.constant;
|
|
|
|
return (light_color / attentuation);
|
|
}
|
|
|
|
vec4 calculate_point_lights() {
|
|
vec4 final_color = vec4(0, 0, 0, 0);
|
|
|
|
for (int i=0; i<point_light_count; i++) {
|
|
final_color += calculate_point_light(point_lights[i]);
|
|
}
|
|
|
|
return final_color;
|
|
}
|
|
|
|
vec4 calculate_spot_light(Spot_Light spot_light) {
|
|
vec3 ray_direction = normalize(frag_pos - spot_light.point_light.position);
|
|
float spot_light_factor = dot(ray_direction, spot_light.direction);
|
|
|
|
if (spot_light_factor > spot_light.edge) {
|
|
vec4 light_color = calculate_point_light(spot_light.point_light);
|
|
|
|
return light_color * (1.0f - (1.0f - spot_light_factor)*(1.0f/(1.0f - spot_light.edge)));
|
|
}
|
|
|
|
return vec4(0, 0, 0, 0);
|
|
}
|
|
|
|
vec4 calculate_spot_lights() {
|
|
vec4 final_color = vec4(0, 0, 0, 0);
|
|
|
|
for (int i=0; i<spot_light_count; i++) {
|
|
final_color += calculate_spot_light(spot_lights[i]);
|
|
}
|
|
|
|
return final_color;
|
|
}
|
|
|
|
void main() {
|
|
vec4 final_color = calculate_light_by_direction(sun.light, sun.direction);
|
|
|
|
final_color += calculate_point_lights();
|
|
final_color += calculate_spot_lights();
|
|
|
|
color = texture(tex, texture_coord) * final_color;
|
|
}
|