187 lines
5.3 KiB
GLSL
187 lines
5.3 KiB
GLSL
#version 330 core
|
|
|
|
layout(location = 0) out vec4 f_color;
|
|
|
|
in vec3 v_normal;
|
|
in vec2 v_texCoord;
|
|
in vec3 v_fragmentPosition;
|
|
|
|
struct Material {
|
|
sampler2D texture_diffuse0;
|
|
sampler2D texture_diffuse1;
|
|
sampler2D texture_specular0;
|
|
sampler2D texture_specular1;
|
|
sampler2D texture_normal0;
|
|
sampler2D texture_normal1;
|
|
sampler2D texture_height0;
|
|
sampler2D texture_height1;
|
|
sampler2D texture_gloss0;
|
|
sampler2D texture_gloss1;
|
|
float shininess;
|
|
};
|
|
uniform Material u_material;
|
|
|
|
struct DirectionalLight {
|
|
bool isActive;
|
|
vec3 direction;
|
|
|
|
vec3 ambient;
|
|
vec3 diffuse;
|
|
vec3 specular;
|
|
};
|
|
uniform DirectionalLight u_directionalLight;
|
|
|
|
struct PointLight {
|
|
bool isActive;
|
|
vec3 position;
|
|
|
|
float K_c;
|
|
float K_l;
|
|
float K_q;
|
|
|
|
vec3 ambient;
|
|
vec3 diffuse;
|
|
vec3 specular;
|
|
};
|
|
#define NUM_POINT_LIGHTS 16
|
|
uniform PointLight u_pointLight[NUM_POINT_LIGHTS];
|
|
|
|
struct SpotLight {
|
|
bool isActive;
|
|
vec3 position;
|
|
vec3 direction;
|
|
|
|
float innerCutOff;
|
|
float outerCutOff;
|
|
|
|
float K_c;
|
|
float K_l;
|
|
float K_q;
|
|
|
|
vec3 ambient;
|
|
vec3 diffuse;
|
|
vec3 specular;
|
|
};
|
|
uniform SpotLight u_spotLight;
|
|
|
|
uniform mat3 u_normalMatrix;
|
|
uniform vec3 u_viewPosition;
|
|
|
|
vec3 directionalLightContribution(DirectionalLight light, vec3 normal, vec3 viewDir);
|
|
vec3 pointLightContribution(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
|
|
vec3 spotLightContribution(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
|
|
|
|
void computeShading(
|
|
vec3 light_ambient, vec3 light_diffuse, vec3 light_specular,
|
|
vec3 lightDir, vec3 viewDir, vec3 normal,
|
|
out vec3 ambient, out vec3 diffuse, out vec3 specular
|
|
);
|
|
|
|
float computeAttenuation(vec3 lightPos, vec3 fragPos, float K_c, float K_l, float K_q);
|
|
|
|
void main() {
|
|
|
|
vec3 fragmentColor = vec3(0.0f);
|
|
|
|
vec3 normal = normalize(u_normalMatrix * v_normal);
|
|
vec3 viewDir = normalize(u_viewPosition - v_fragmentPosition);
|
|
|
|
fragmentColor += directionalLightContribution(u_directionalLight, normal, viewDir);
|
|
|
|
for(int i = 0; i < NUM_POINT_LIGHTS; i++) {
|
|
fragmentColor += pointLightContribution(u_pointLight[i], normal, v_fragmentPosition, viewDir);
|
|
}
|
|
|
|
//fragmentColor += spotLightContribution(u_spotLight, normal, v_fragmentPosition, viewDir);
|
|
|
|
f_color = vec4(fragmentColor, 1.0f);
|
|
|
|
}
|
|
|
|
vec3 directionalLightContribution(DirectionalLight light, vec3 normal, vec3 viewDir) {
|
|
|
|
// Only compute if light source is active
|
|
if(!light.isActive)
|
|
return vec3(0.0f);
|
|
|
|
vec3 lightDir = normalize(-light.direction);
|
|
|
|
vec3 ambient, diffuse, specular;
|
|
computeShading(light.ambient, light.diffuse, light.specular, lightDir, viewDir, normal, ambient, diffuse, specular);
|
|
|
|
return (ambient + diffuse + specular);
|
|
}
|
|
|
|
vec3 pointLightContribution(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) {
|
|
|
|
// Only compute if light source is active
|
|
if(!light.isActive)
|
|
return vec3(0.0f);
|
|
|
|
vec3 lightDir = normalize(light.position - fragPos);
|
|
|
|
vec3 ambient, diffuse, specular;
|
|
computeShading(light.ambient, light.diffuse, light.specular, lightDir, viewDir, normal, ambient, diffuse, specular);
|
|
|
|
float attenuation = computeAttenuation(light.position, fragPos, light.K_c, light.K_l, light.K_q);
|
|
ambient *= attenuation;
|
|
diffuse *= attenuation;
|
|
specular *= attenuation;
|
|
|
|
return (ambient + diffuse + specular);
|
|
}
|
|
|
|
vec3 spotLightContribution(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir) {
|
|
|
|
// Only compute if light source is active
|
|
if(!light.isActive)
|
|
return vec3(0.0f);
|
|
|
|
vec3 lightDir = normalize(light.position - fragPos);
|
|
|
|
vec3 ambient, diffuse, specular;
|
|
computeShading(light.ambient, light.diffuse, light.specular, lightDir, viewDir, normal, ambient, diffuse, specular);
|
|
|
|
float attenuation = computeAttenuation(light.position, fragPos, light.K_c, light.K_l, light.K_q);
|
|
ambient *= attenuation;
|
|
diffuse *= attenuation;
|
|
specular *= attenuation;
|
|
|
|
float theta = dot(lightDir, normalize(-light.direction));
|
|
float epsilon = light.innerCutOff - light.outerCutOff;
|
|
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0f, 1.0f);
|
|
|
|
diffuse *= intensity;
|
|
specular *= intensity;
|
|
|
|
return (ambient + diffuse + specular);
|
|
}
|
|
|
|
void computeShading(
|
|
vec3 light_ambient, vec3 light_diffuse, vec3 light_specular,
|
|
vec3 lightDir, vec3 viewDir, vec3 normal,
|
|
out vec3 ambient, out vec3 diffuse, out vec3 specular) {
|
|
|
|
// Diffuse shading
|
|
float diffuseShading = max(dot(normal, lightDir), 0.0f);
|
|
|
|
// Specular shading
|
|
vec3 reflectDir = reflect(-lightDir, normal);
|
|
float specularShading = pow(max(dot(viewDir, reflectDir), 0.0f), u_material.shininess);
|
|
|
|
vec4 diffuseTex = texture(u_material.texture_diffuse0, v_texCoord);
|
|
vec4 specularTex = texture(u_material.texture_specular0, v_texCoord);
|
|
|
|
ambient = light_ambient * vec3(diffuseTex);
|
|
diffuse = light_diffuse * diffuseShading * vec3(diffuseTex);
|
|
specular = light_specular * specularShading * vec3(specularTex);
|
|
|
|
}
|
|
|
|
float computeAttenuation(vec3 lightPos, vec3 fragPos, float K_c, float K_l, float K_q) {
|
|
|
|
float distanceLightFragment = length(lightPos - fragPos);
|
|
return 1.0f / (K_c + K_l * distanceLightFragment + K_q * distanceLightFragment * distanceLightFragment);
|
|
|
|
}
|