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