2 * \file toon_lighting.glsl
3 * \brief Toon 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 = dot(s, n);
104 diffuse += lights[idx].diffuse;
106 else if (sDotN > 0.6) {
107 diffuse += lights[idx].diffuse * 0.75;
109 else if (sDotN > 0.3) {
110 diffuse += lights[idx].diffuse * 0.5;
113 diffuse += lights[idx].diffuse * 0.25;
118 float hDotN = dot(lights[idx].halfVector.xyz, n);
120 specular += lights[idx].specular;
125 void pointLight(const in int idx, const in vec3 ecVertex, const in vec3 v, const in vec3 n,
126 inout vec4 ambient, inout vec4 diffuse, inout vec4 specular) {
128 // normalized light source direction and half vector
129 vec3 s = normalize(lights[idx].position.xyz - ecVertex);
130 vec3 h = normalize(v + s);
133 ambient += lights[idx].ambient;
136 float sDotN = dot(s, n);
139 diffuse += lights[idx].diffuse;
141 else if (sDotN > 0.6) {
142 diffuse += lights[idx].diffuse * 0.75;
144 else if (sDotN > 0.3) {
145 diffuse += lights[idx].diffuse * 0.5;
148 diffuse += lights[idx].diffuse * 0.25;
153 float hDotN = dot(h, n);
155 specular += lights[idx].specular;
160 void spotLight(const in int idx, const in vec3 ecVertex, const in vec3 v, const in vec3 n,
161 inout vec4 ambient, inout vec4 diffuse, inout vec4 specular) {
163 // normalized light source direction and half vector
164 vec3 s = normalize(lights[idx].position.xyz - ecVertex);
165 vec3 h = normalize(v + s);
167 // check if surface point is inside spotlight cone
168 float dirDotS = dot(lights[idx].spotDirection.xyz, -s);
169 if (dirDotS >= lights[idx].spotCosCutoff) {
171 // spot attenuation from center to edges
172 float attenuation = pow(dirDotS, lights[idx].spotExponent);
175 ambient += attenuation * lights[idx].ambient;
178 float sDotN = dot(s, n);
181 diffuse += lights[idx].diffuse;
183 else if (sDotN > 0.6) {
184 diffuse += lights[idx].diffuse * 0.75;
186 else if (sDotN > 0.3) {
187 diffuse += lights[idx].diffuse * 0.5;
190 diffuse += lights[idx].diffuse * 0.25;
195 float hDotN = dot(h, n);
197 specular += lights[idx].specular;