From fc8d7fed3ccdf0998a7b9809aa825f2d14876b29 Mon Sep 17 00:00:00 2001 From: jvech Date: Fri, 16 Sep 2022 16:21:37 -0500 Subject: learn: 17. Multiple lights --- shaders/color.fsh | 127 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 114 insertions(+), 13 deletions(-) (limited to 'shaders') diff --git a/shaders/color.fsh b/shaders/color.fsh index c2a8dc7..a0958ed 100644 --- a/shaders/color.fsh +++ b/shaders/color.fsh @@ -1,4 +1,5 @@ -# version 330 core +#version 330 core +#define NR_POINT_LIGHTS 4 struct Material { sampler2D diffuse; @@ -6,13 +7,41 @@ struct Material { float shininess; }; -struct Light { +struct DirLight { + vec3 direction; + + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +struct PointLight { vec3 position; + + float constant; + float linear; + float quadratic; + vec3 ambient; vec3 diffuse; vec3 specular; }; +struct FlashLight { + vec3 position; + vec3 direction; + + vec3 ambient; + vec3 diffuse; + vec3 specular; + + float cutOff; + float outerCutOff; + float constant; + float linear; + float quadratic; +}; + in vec3 Normal; in vec3 FragPos; in vec2 TexCoords; @@ -21,24 +50,96 @@ out vec4 FragColor; uniform vec3 viewPos; uniform Material material; -uniform Light light; +uniform DirLight dirLight; +uniform PointLight pointLight[NR_POINT_LIGHTS]; +uniform FlashLight flashLight; -void main() +vec3 calcDirLight(DirLight light, vec3 normal, vec3 viewDir) { - // ambient + vec3 lightDir = normalize(-light.direction); + // diffuse + float diff = max(dot(normal, lightDir), 0.0); + // specular + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb; - + vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb; + vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb; + + return (ambient + diffuse + specular); +} + +vec3 calcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) +{ + vec3 lightDir = normalize(light.position - fragPos); // diffuse - vec3 norm = normalize(Normal); - vec3 lightDir = normalize(light.position - FragPos); - float diff = max(dot(norm, lightDir), 0.0); + float diff = max(dot(normal, lightDir), 0.0); + + //specular + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + + //attenuation + float dist = length(light.position - fragPos); + float attenuation = 1.0 / (light.constant + light.linear * dist + + light.quadratic * (dist * dist)); + + vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb; vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb; + vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb; - // specular - vec3 viewDir = normalize(viewPos - FragPos); - vec3 reflectDir = reflect(-lightDir, norm); + ambient *= attenuation; + diffuse *= attenuation; + specular *= attenuation; + + return ambient + diffuse + specular; +} + +vec3 calcFlashLight(FlashLight light, vec3 normal, vec3 fragPos, vec3 viewDir) +{ + vec3 lightDir = normalize(light.position - fragPos); + float theta = dot(lightDir, normalize(-light.direction)); + float epsilon = light.cutOff - light.outerCutOff; + float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); + + // diffuse + float diff = max(dot(normal, lightDir), 0.0); + + //specular + vec3 reflectDir = reflect(-lightDir, normal); float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + + //attenuation + float dist = length(light.position - fragPos); + float attenuation = 1.0 / (light.constant + light.linear * dist + + light.quadratic * (dist * dist)); + + vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb; + vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb; vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb; - FragColor = vec4((specular + ambient + diffuse), 1.0f); + diffuse *= attenuation * intensity; + specular *= attenuation * intensity; + + return ambient + diffuse + specular; +} + +void main() +{ + // properties + vec3 norm = normalize(Normal); + vec3 viewDir = normalize(viewPos - FragPos); + + // 1. Directional light + vec3 result = calcDirLight(dirLight, norm, viewDir); + + // 2. Point lights + for (int i = 0; i < NR_POINT_LIGHTS; i++) + result += calcPointLight(pointLight[i], norm, FragPos, viewDir); + + // 3. Spot light + result += calcFlashLight(flashLight, norm, FragPos, viewDir); + + FragColor = vec4(result, 1.0); } -- cgit v1.2.3-70-g09d2