2018-02-19 23:13:05 +00:00
|
|
|
|
|
|
|
vec3 lightContribution(int i, vec3 normal)
|
|
|
|
{
|
|
|
|
vec4 lightpos = lights[i];
|
|
|
|
vec4 lightcolor = lights[i+1];
|
|
|
|
vec4 lightspot1 = lights[i+2];
|
|
|
|
vec4 lightspot2 = lights[i+3];
|
|
|
|
|
|
|
|
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
|
|
|
|
if (lightpos.w < lightdistance)
|
|
|
|
return vec3(0.0); // Early out lights touching surface but not this fragment
|
2018-05-19 17:20:45 +00:00
|
|
|
|
2018-05-19 19:17:58 +00:00
|
|
|
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
|
2018-05-19 17:20:45 +00:00
|
|
|
float dotprod = dot(normal, lightdir);
|
|
|
|
if (dotprod < 0.0) return vec3(0.0); // light hits from the backside. This can happen with full sector light lists and must be rejected for all cases.
|
2018-02-19 23:13:05 +00:00
|
|
|
|
|
|
|
float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);
|
|
|
|
|
|
|
|
if (lightspot1.w == 1.0)
|
|
|
|
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
|
|
|
|
|
|
|
if (lightcolor.a < 0.0) // Sign bit is the attenuated light flag
|
|
|
|
{
|
2018-05-19 17:20:45 +00:00
|
|
|
attenuation *= clamp(dotprod, 0.0, 1.0);
|
2018-02-19 23:13:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (attenuation > 0.0) // Skip shadow map test if possible
|
|
|
|
{
|
|
|
|
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
|
|
|
|
return lightcolor.rgb * attenuation;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return vec3(0.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vec3 ProcessMaterial(vec3 material, vec3 color)
|
|
|
|
{
|
2018-03-12 20:44:55 +00:00
|
|
|
vec4 dynlight = uDynLightColor;
|
|
|
|
vec3 normal = ApplyNormalMap();
|
|
|
|
|
2018-02-19 23:13:05 +00:00
|
|
|
if (uLightIndex >= 0)
|
|
|
|
{
|
|
|
|
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
|
|
|
if (lightRange.z > lightRange.x)
|
|
|
|
{
|
|
|
|
// modulated lights
|
|
|
|
for(int i=lightRange.x; i<lightRange.y; i+=4)
|
|
|
|
{
|
|
|
|
dynlight.rgb += lightContribution(i, normal);
|
|
|
|
}
|
|
|
|
|
|
|
|
// subtractive lights
|
|
|
|
for(int i=lightRange.y; i<lightRange.z; i+=4)
|
|
|
|
{
|
|
|
|
dynlight.rgb -= lightContribution(i, normal);
|
|
|
|
}
|
|
|
|
}
|
2018-03-12 20:44:55 +00:00
|
|
|
}
|
2018-02-19 23:13:05 +00:00
|
|
|
|
2018-03-12 20:44:55 +00:00
|
|
|
vec3 frag = material * clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
|
2018-02-19 23:13:05 +00:00
|
|
|
|
2018-03-12 20:44:55 +00:00
|
|
|
if (uLightIndex >= 0)
|
|
|
|
{
|
|
|
|
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
2018-02-19 23:13:05 +00:00
|
|
|
if (lightRange.w > lightRange.z)
|
|
|
|
{
|
|
|
|
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
|
|
|
|
|
|
|
|
// additive lights
|
|
|
|
for(int i=lightRange.z; i<lightRange.w; i+=4)
|
|
|
|
{
|
|
|
|
addlight.rgb += lightContribution(i, normal);
|
|
|
|
}
|
|
|
|
|
|
|
|
frag = clamp(frag + desaturate(addlight).rgb, 0.0, 1.0);
|
|
|
|
}
|
|
|
|
}
|
2018-03-12 20:44:55 +00:00
|
|
|
|
|
|
|
return frag;
|
2018-02-19 23:13:05 +00:00
|
|
|
}
|