1const float CONSTANT_ATTENUATION = 1.0;
2const float LINEAR_ATTENUATION = 0.0;
3const float QUADRATIC_ATTENUATION = 1.0;
4
5in vec3 position;
6in vec2 texcoord;
7in vec4 color;
8in vec3 normal;
9
10uniform highp mat4 modelMatrix;
11uniform highp mat4 viewMatrix;
12uniform highp mat4 projMatrix;
13uniform highp mat4 extraMatrix;
14uniform bool textured;
15uniform bool lightsEnabled;
16uniform highp vec2 texScale;
17
18const int maxLights = 8;
19uniform vec4 lightsPosition[maxLights];
20uniform vec4 lightsDirection[maxLights];
21uniform vec4 lightsColor[maxLights];
22uniform vec4 lightsParams[maxLights];
23
24struct shadow_info {
25	bool _active;
26	vec3 _color;
27	vec3 _light;
28	vec3 _point;
29	vec3 _normal;
30};
31
32uniform shadow_info shadow;
33
34out vec2 Texcoord;
35out vec4 Color;
36
37void main()
38{
39	vec4 pos = modelMatrix * extraMatrix * vec4(position, 1.0);
40
41	// See http://en.wikipedia.org/wiki/Line-plane_intersection
42	if (shadow._active) {
43		pos /= pos.w;
44		vec3 l = pos.xyz - shadow._light;
45		float d = dot(shadow._point - shadow._light, shadow._normal) / dot(l, shadow._normal);
46		vec3 p = shadow._light + d * l;
47		pos = vec4(p, 1.0);
48	}
49
50	vec4 positionView = viewMatrix * pos;
51	gl_Position = projMatrix * positionView;
52
53	if (shadow._active) {
54		Color = vec4(shadow._color, 1.0);
55	} else {
56		Color = color;
57	}
58
59	if (textured) {
60		Texcoord = vec2(0.0, 1.0) + (texcoord / texScale);
61	} else {
62		Texcoord = vec2(0.0, 0.0);
63	}
64
65	vec3 light = vec3(0.0, 0.0, 0.0);
66	vec3 normalEye = normalize((viewMatrix * (modelMatrix * extraMatrix * vec4(normal, 0.0))).xyz);
67
68	for (int i = 0; i < maxLights; ++i) {
69		float intensity = lightsColor[i].w;
70		float light_type = lightsPosition[i].w;
71		if (light_type >= 0.0) { // Not ambient
72			vec3 vertexToLight = lightsPosition[i].xyz;
73			if (light_type > 0.0) { // positional light
74				vertexToLight -= positionView.xyz;
75				float dist = length(vertexToLight);
76				intensity /= CONSTANT_ATTENUATION + dist * (LINEAR_ATTENUATION + dist * QUADRATIC_ATTENUATION);
77				if (lightsDirection[i].w > -1.0) { // Spotlight
78					// See DirectX spotlight documentation
79					float cosAngle = -dot(normalize(vertexToLight), normalize(lightsDirection[i].xyz)); // rho
80					float cosPenumbra = clamp(lightsParams[i].w, 0.0, 1.0); // cos(theta / 2)
81					float cosUmbra = clamp(lightsParams[i].z, 0.0, cosPenumbra); // cos(phi / 2)
82					if (cosAngle <= cosPenumbra) {
83						if (cosAngle < cosUmbra || cosPenumbra == cosUmbra) {
84							intensity = 0.0;
85						} else {
86							intensity *= (cosAngle - cosUmbra) / (cosPenumbra - cosUmbra);
87						}
88					}
89				}
90			}
91			intensity *= max(0.0, dot(normalEye, normalize(vertexToLight)));
92		}
93		light += lightsColor[i].xyz * intensity;
94	}
95	light /= max(1.0, max(max(light.x, light.y), light.z));
96	Color *= vec4(light, 1.0);
97}
98