#ifdef GL_ES precision mediump float; #endif varying vec2 texCoordVar; varying vec3 varNormal; varying vec4 varPosition; varying vec4 rawPosition; uniform sampler2D diffuse; uniform mat4 modelMatrix; uniform vec4 diffuse_color; uniform vec4 specular_color; uniform vec4 entityColor; uniform float shininess; uniform float shadowAmount; #define MAX_LIGHTS 8 #define MAX_LIGHT_SHADOWS 2 struct LightInfo { vec3 position; vec3 direction; vec4 specular; vec4 diffuse; float spotExponent; float spotCosCutoff; float constantAttenuation; float linearAttenuation; float quadraticAttenuation; float shadowEnabled; }; struct LightShadowInfo { sampler2D shadowBuffer; mat4 shadowMatrix; }; uniform LightInfo lights[MAX_LIGHTS]; uniform LightShadowInfo lightsShadows[MAX_LIGHT_SHADOWS]; float calculateAttenuation(in int i, in float dist) { return(1.0 / (lights[i].constantAttenuation + lights[i].linearAttenuation * dist + lights[i].quadraticAttenuation * dist * dist)); } void pointLight(in int i, in vec3 normal, in vec4 pos, inout vec4 diffuse, inout vec4 specular) { vec4 color = diffuse_color; vec4 matspec = specular_color; float shininess = shininess; vec4 lightspec = lights[i].specular; vec4 lpos = vec4(lights[i].position, 1.0); vec4 s = pos-lpos; vec4 sn = -normalize(s); vec3 light = sn.xyz; vec3 n = normalize(normal); vec3 r = -reflect(light, n); r = normalize(r); vec3 v = -pos.xyz; v = normalize(v); float nDotL = dot(n, sn.xyz); if(nDotL > 0.0) { float dist = length(s); float attenuation = calculateAttenuation(i, dist); diffuse += color * max(0.0, nDotL) * lights[i].diffuse * attenuation; if (shininess != 0.0) { specular += lightspec * matspec * pow(max(0.0,dot(r, v)), shininess) * attenuation; } } } void spotLight(in int i, in vec3 normal, in vec4 pos, inout vec4 diffuse, inout vec4 specular, in float shadow) { vec4 color = diffuse_color; vec4 matspec = specular_color; float shininess = shininess; vec4 lightspec = lights[i].specular; vec4 lpos = vec4(lights[i].position, 1.0); vec4 s = pos-lpos; vec4 sn = -normalize(s); vec3 light = sn.xyz; vec3 n = normalize(normal); vec3 r = -reflect(light, n); r = normalize(r); vec3 v = -pos.xyz; v = normalize(v); float cos_outer_cone_angle = (1.0-lights[i].spotExponent) * lights[i].spotCosCutoff; float cos_cur_angle = dot(-normalize(lights[i].direction), sn.xyz); float cos_inner_cone_angle = lights[i].spotCosCutoff; float cos_inner_minus_outer_angle = cos_inner_cone_angle - cos_outer_cone_angle; float spot = 0.0; spot = clamp((cos_cur_angle - cos_outer_cone_angle) / cos_inner_minus_outer_angle, 0.0, 1.0); float nDotL = dot(n, sn.xyz); if(nDotL > 0.0) { float dist = length(s); float attenuation = calculateAttenuation(i, dist); diffuse += color * max(0.0, nDotL) * lights[i].diffuse * attenuation * spot * shadow; if (shininess != 0.0) { specular += lightspec * matspec * pow(max(0.0,dot(r, v)), shininess) * attenuation * spot * shadow; } } } void doSpotLightShadow(in int i, in vec3 normal, in vec4 pos, inout vec4 diffuse, inout vec4 specular, inout int shadowIndex) { if(lights[i].shadowEnabled == 1.0) { float shadow = 1.0; float bias = 0.00001; if(shadowIndex == 0) { vec4 shadowCoord = lightsShadows[0].shadowMatrix * modelMatrix * rawPosition; vec4 shadowCoordinateWdivide = shadowCoord / shadowCoord.w; float distanceFromLight = texture2D(lightsShadows[0].shadowBuffer, shadowCoordinateWdivide.st).z; if (shadowCoordinateWdivide.x > 0.001 && shadowCoordinateWdivide.y > 0.001 && shadowCoordinateWdivide.x < 0.999 && shadowCoordinateWdivide.y < 0.999) { shadow = step(shadowCoordinateWdivide.z, distanceFromLight+bias); } } else { vec4 shadowCoord = lightsShadows[1].shadowMatrix * modelMatrix * rawPosition; vec4 shadowCoordinateWdivide = shadowCoord / shadowCoord.w; float distanceFromLight = texture2D(lightsShadows[1].shadowBuffer, shadowCoordinateWdivide.st).z; if (shadowCoordinateWdivide.x > 0.001 && shadowCoordinateWdivide.y > 0.001 && shadowCoordinateWdivide.x < 0.999 && shadowCoordinateWdivide.y < 0.999) { shadow = step(shadowCoordinateWdivide.z, distanceFromLight+bias); } } shadowIndex++; spotLight(i, normal, pos, diffuse, specular, shadow); } else { spotLight(i, normal, pos, diffuse, specular, 1.0); } } void doLights(in int numLights, in vec3 normal, in vec4 pos, inout vec4 diffuse, inout vec4 specular) { int shadowIndex = 0; for (int i = 0; i < numLights; i++) { if (lights[i].spotCosCutoff == 180.0) { pointLight(i, normal, pos, diffuse, specular); } else { doSpotLightShadow(i, normal, pos, diffuse, specular, shadowIndex); } } } void main() { vec4 diffuse_val = vec4(0.0); vec4 specular_val = vec4(0.0); doLights(MAX_LIGHTS, varNormal, varPosition, diffuse_val, specular_val); vec4 texColor = texture2D(diffuse, texCoordVar); vec4 color = diffuse_val; color = clamp((color*entityColor*texColor) + specular_val, 0.0, 1.0); color.a = entityColor.a * texColor.a * diffuse_color.a; gl_FragColor = color; }