#version 450 #extension GL_ARB_separate_shader_objects : enable #define MAX_LIGHTS 4 struct Material { vec4 color; bool diffused; float specular; float shininess; }; struct AmbientPointLight { vec3 color; vec3 pos; }; struct PointLight { vec3 color; float constant; vec3 pos; float linear; float quadratic; }; struct SpotLight { vec3 color; float innerCutOff; vec3 pos; float outerCutOff; vec3 dir; float constant; float linear; float quadratic; }; layout(std140, binding = 1) uniform Data { vec3 ambient; bool preMultiply; vec3 camPos; Material material; uint ambientPointLightCount; uint pointLightCount; uint spotLightCount; AmbientPointLight ambientLights[MAX_LIGHTS]; PointLight pointLights[MAX_LIGHTS]; SpotLight spotLights[MAX_LIGHTS]; } data; layout(location = 1) in vec3 fNorm; layout(location = 0) in vec4 fWorldPos; layout(location = 0) out vec4 result; vec3 CalcAmbientPointLight(vec3 normal, vec3 vertexPos, vec3 viewDir, Material material, AmbientPointLight light) { vec3 lightDir = normalize(light.pos - vertexPos); vec3 diffuse = light.color * max(dot(normal, lightDir), 0.0f); vec3 specular = light.color * pow(max(dot(normal, normalize(lightDir + viewDir)), 0.0), material.shininess); return diffuse + specular; } vec3 CalcPointLight(vec3 normal, vec3 vertexPos, vec3 viewDir, Material material, PointLight light) { vec3 lightDir = normalize(light.pos - vertexPos); float dist = length(light.pos - vertexPos); float attenuation = 1.0f / (light.constant + light.linear * dist + light.quadratic * (dist * dist)); vec3 diffuse = light.color * max(dot(normal, lightDir), 0.0f); vec3 specular = light.color * pow(max(dot(normal, normalize(lightDir + viewDir)), 0.0), material.shininess); return (diffuse + specular) * attenuation; } vec3 CalcSpotLight(vec3 normal, vec3 vertexPos, vec3 viewDir, Material material, SpotLight light) { vec3 lightDir = normalize(light.pos - vertexPos); float dist = length(light.pos - vertexPos); float attenuation = 1.0f / (light.constant + light.linear * dist + light.quadratic * (dist * dist)); float theta = dot(lightDir, normalize(-light.dir)); float epsilon = light.innerCutOff - light.outerCutOff; float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0f, 1.0f); vec3 diffuse = light.color * max(dot(normal, lightDir), 0.0f); vec3 specular = light.color * pow(max(dot(normal, normalize(lightDir + viewDir)), 0.0), material.shininess); return (diffuse + specular) * intensity * attenuation; } void main() { if (data.material.diffused == true) { vec3 viewDir = normalize(data.camPos - fWorldPos.xyz); vec3 nNorm = normalize(fNorm); vec3 final = data.ambient; //Ambient Point Lights for (uint i = 0; i < data.ambientPointLightCount; ++i) final += CalcAmbientPointLight(nNorm, fWorldPos.xyz, viewDir, data.material, data.ambientLights[i]); //Point Lights for (uint i = 0; i < data.pointLightCount; ++i) final += CalcPointLight(nNorm, fWorldPos.xyz, viewDir, data.material, data.pointLights[i]); //Spot Lights for (uint i = 0; i < data.spotLightCount; ++i) final += CalcSpotLight(nNorm, fWorldPos.xyz, viewDir, data.material, data.spotLights[i]); //outColor = vec4(data.spotLights[0].quadratic, 0.0f, 0.0f, 1.0f); result = vec4(data.material.color.rgb * final, data.material.color.a); } else { result = data.material.color; } if (data.preMultiply) result = vec4(result.rgb * result.a, result.a); }