2 * \file blinn_phong_lighting.glsl
3 * \brief Blinn Phong lighting shader, provides external function applyLighting()
4 * to vertex or fragment shader.
9 const int MAX_NUMBER_OF_LIGHTS = 10;
16 vec4 halfVector; // used as vec3, expected as normalized
17 vec4 spotDirection; // used as vec3, expected as normalized
22 layout(std140) uniform LightBlock {
23 Light lights[MAX_NUMBER_OF_LIGHTS];
34 layout(std140) uniform MaterialBlock {
39 uniform vec4 globalAmbientLight;
42 // --- declarations ---
45 void directionalLight(const in int idx, const in vec3 v, const in vec3 n,
46 inout vec4 ambient, inout vec4 diffuse, inout vec4 specular);
48 void pointLight(const in int idx, const in vec3 ecVertex, const in vec3 v, const in vec3 n,
49 inout vec4 ambient, inout vec4 diffuse, inout vec4 specular);
51 void spotLight(const in int idx, const in vec3 ecVertex, const in vec3 v, const in vec3 n,
52 inout vec4 ambient, inout vec4 diffuse, inout vec4 specular);
55 // --- implementations ---
58 void applyLighting(const in vec3 ecVertex, const in vec3 ecNormal,
59 out vec4 emissionAmbientDiffuse, out vec4 specular) {
61 // normalized view direction and surface normal
62 vec3 v = normalize(-ecVertex);
63 vec3 n = normalize(ecNormal);
65 // add contributions of light sources
66 vec4 ambient = vec4(0., 0., 0., 0.);
67 vec4 diffuse = vec4(0., 0., 0., 0.);
68 specular = vec4(0., 0., 0., 0.);
69 for (int i = 0; i < nLights; ++i) {
70 if (lights[i].position.w < 0.001) {
71 directionalLight(i, v, n, ambient, diffuse, specular);
74 if (lights[i].spotCosCutoff < 0.001) {
75 pointLight(i, ecVertex, v, n, ambient, diffuse, specular);
78 spotLight(i, ecVertex, v, n, ambient, diffuse, specular);
83 // multiply with material parameters, add emission and global ambient light
84 emissionAmbientDiffuse = material.emission
85 + material.ambient * (globalAmbientLight + ambient)
86 + material.diffuse * diffuse;
87 specular *= material.specular;
91 void directionalLight(const in int idx, const in vec3 v, const in vec3 n,
92 inout vec4 ambient, inout vec4 diffuse, inout vec4 specular) {
94 // normalized light source direction (half vector is provided by application)
95 vec3 s = normalize(lights[idx].position.xyz);
98 ambient += lights[idx].ambient;
101 float sDotN = max(0., dot(s, n));
102 diffuse += lights[idx].diffuse * sDotN;
105 float hDotN = dot(lights[idx].halfVector.xyz, n);
107 specular += lights[idx].specular * pow(hDotN, material.shininess);
112 void pointLight(const in int idx, const in vec3 ecVertex, const in vec3 v, const in vec3 n,
113 inout vec4 ambient, inout vec4 diffuse, inout vec4 specular) {
115 // normalized light source direction and half vector
116 vec3 s = normalize(lights[idx].position.xyz - ecVertex);
117 vec3 h = normalize(v + s);
120 ambient += lights[idx].ambient;
123 float sDotN = max(0., dot(s, n));
124 diffuse += lights[idx].diffuse * sDotN;
127 float hDotN = dot(h, n);
129 specular += lights[idx].specular * pow(hDotN, material.shininess);
134 void spotLight(const in int idx, const in vec3 ecVertex, const in vec3 v, const in vec3 n,
135 inout vec4 ambient, inout vec4 diffuse, inout vec4 specular) {
137 // normalized light source direction and half vector
138 vec3 s = normalize(lights[idx].position.xyz - ecVertex);
139 vec3 h = normalize(v + s);
141 // check if surface point is inside spotlight cone
142 float dirDotS = dot(lights[idx].spotDirection.xyz, -s);
143 if (dirDotS >= lights[idx].spotCosCutoff) {
145 // spot attenuation from center to edges
146 float attenuation = pow(dirDotS, lights[idx].spotExponent);
149 ambient += attenuation * lights[idx].ambient;
152 float sDotN = max(0., dot(s, n));
153 diffuse += attenuation * lights[idx].diffuse * sDotN;
156 float hDotN = dot(h, n);
158 specular += attenuation * lights[idx].specular * pow(hDotN, material.shininess);