Download
struct SpotLight {
vec3 Intensity;
vec3 Position;
vec3 Direction;
float AttenuationConstant;
float AttenuationLinear;
float AttenuationQuadratic;
float ConcentrationExponent;
};
Spot Lights have the same properties like point lights, but they have additionally a direction in which they are pointing and a exponent to dim the intensity depending on the angle between the spotlights direction and the direction to the the lit surface.
The attenuation depends on the angle between X and L, we use a modified "cosine" function to determine the angular attenuation.
To make the spot light "sharper", we use high values as exponent for the cosine function.
The reason why we dont use a simple angle (instead of the concentration exponent) is because that would give us sharp edges between the area that is lit and the dark area, that would look like the following picture:
Shader Source Code:
Fragment Shader: "model.fragmentshader.txt"
#version 450 core
struct Material {
vec3 Kd; // diffuse
vec3 Ks; // specular
float Ns; // shininess
};
struct DirectionalLight {
vec3 Intensity;
vec3 Direction;
};
struct PointLight {
vec3 Intensity;
vec3 Position;
float AttenuationConstant;
float AttenuationLinear;
float AttenuationQuadratic;
};
struct SpotLight {
vec3 Intensity;
vec3 Position;
vec3 Direction;
float AttenuationConstant;
float AttenuationLinear;
float AttenuationQuadratic;
float ConcentrationExponent;
};
in VS_FS_INTERFACE {
vec3 position;
vec3 normal;
} vertex;
// example material and other lighting properties
uniform Material material = Material ( vec3(0, 0, 0), vec3(0, 0, 0), 0 );
uniform vec3 AmbientIntensity = vec3(0, 0, 0);
uniform vec3 CameraPosition = vec3(0, 0, 0);
out layout (location = 0) vec4 out_color;
void main ()
{
// material
vec3 Kd = material.Kd;
vec3 Ks = material.Ks;
float Ns = material.Ns;
// light parts
vec3 Ia = AmbientIntensity;
vec3 Id = vec3(0, 0, 0);
vec3 Is = vec3(0, 0, 0);
// process light sources here ...
SpotLight light = SpotLight( vec3(1, 1, 1), vec3(-2, 5, 3), vec3(2, -5, -3), 1.0f, 0.0f, 0.01f, 50.0f);
vec3 N = normalize(vertex.normal);
vec3 L = normalize(light.Position - vertex.position);
vec3 R = normalize(reflect(-L, N));
vec3 V = normalize(CameraPosition - vertex.position);
vec3 X = normalize(-light.Direction);
float Distance = length(light.Position - vertex.position);
float Attenuation = pow(max(0, dot(L, X)), max(0, light.ConcentrationExponent)) / (
light.AttenuationConstant +
light.AttenuationLinear * Distance +
light.AttenuationQuadratic * Distance * Distance);
// diffuse Intensity
Id = Id + light.Intensity * max(0, dot(N, L)) * Attenuation;
// specular intensity
Is = Is + light.Intensity * max(0, pow(max(0, dot(R, V)), max(1, Ns))) * Attenuation;
// final fragment color
vec3 color = Kd * (Ia + Id) + Ks * Is;
out_color = vec4(color, 1);
}