#ifndef LIB_LIGHT_LIGHTING #define LIB_LIGHT_LIGHTING #include "lighting_util.glsl" void perLightSun(out vec3 diffuseOut, vec3 viewPos, vec3 viewNormal) { vec3 lightDir = normalize(lcalcPosition(0)); float lambert = dot(viewNormal.xyz, lightDir); #ifndef GROUNDCOVER lambert = max(lambert, 0.0); #else float eyeCosine = dot(normalize(viewPos), viewNormal.xyz); if (lambert < 0.0) { lambert = -lambert; eyeCosine = -eyeCosine; } lambert *= clamp(-8.0 * (1.0 - 0.3) * eyeCosine + 1.0, 0.3, 1.0); #endif diffuseOut = lcalcDiffuse(0).xyz * lambert; } void perLightPoint(out vec3 ambientOut, out vec3 diffuseOut, int lightIndex, vec3 viewPos, vec3 viewNormal) { vec3 lightPos = lcalcPosition(lightIndex) - viewPos; float lightDistance = length(lightPos); // cull non-FFP point lighting by radius, light is guaranteed to not fall outside this bound with our cutoff #if !@lightingMethodFFP float radius = lcalcRadius(lightIndex); if (lightDistance > radius * 2.0) { ambientOut = vec3(0.0); diffuseOut = vec3(0.0); return; } #endif lightPos = normalize(lightPos); float illumination = lcalcIllumination(lightIndex, lightDistance); ambientOut = lcalcAmbient(lightIndex) * illumination; float lambert = dot(viewNormal.xyz, lightPos) * illumination; #ifndef GROUNDCOVER lambert = max(lambert, 0.0); #else float eyeCosine = dot(normalize(viewPos), viewNormal.xyz); if (lambert < 0.0) { lambert = -lambert; eyeCosine = -eyeCosine; } lambert *= clamp(-8.0 * (1.0 - 0.3) * eyeCosine + 1.0, 0.3, 1.0); #endif diffuseOut = lcalcDiffuse(lightIndex) * lambert; } #if PER_PIXEL_LIGHTING void doLighting(vec3 viewPos, vec3 viewNormal, float shadowing, out vec3 diffuseLight, out vec3 ambientLight) #else void doLighting(vec3 viewPos, vec3 viewNormal, out vec3 diffuseLight, out vec3 ambientLight, out vec3 shadowDiffuse) #endif { vec3 ambientOut, diffuseOut; perLightSun(diffuseOut, viewPos, viewNormal); ambientLight = gl_LightModel.ambient.xyz; #if PER_PIXEL_LIGHTING diffuseLight = diffuseOut * shadowing; #else shadowDiffuse = diffuseOut; diffuseLight = vec3(0.0); #endif for (int i = @startLight; i < @endLight; ++i) { #if @lightingMethodUBO perLightPoint(ambientOut, diffuseOut, PointLightIndex[i], viewPos, viewNormal); #else perLightPoint(ambientOut, diffuseOut, i, viewPos, viewNormal); #endif ambientLight += ambientOut; diffuseLight += diffuseOut; } } float calcSpecIntensity(vec3 viewNormal, vec3 viewDir, float shininess, vec3 lightDir) { if (dot(viewNormal, lightDir) > 0.0) { vec3 halfVec = normalize(lightDir - viewDir); float NdotH = max(dot(viewNormal, halfVec), 0.0); return pow(NdotH, shininess); } return 0.0; } vec3 getSpecular(vec3 viewNormal, vec3 viewPos, float shininess, float shadowing) { shininess = max(shininess, 1e-4); vec3 viewDir = normalize(viewPos); vec3 specularLight = lcalcSpecular(0).xyz * calcSpecIntensity(viewNormal, viewDir, shininess, normalize(lcalcPosition(0))); specularLight *= shadowing; for (int i = @startLight; i < @endLight; ++i) { #if @lightingMethodUBO int lightIndex = PointLightIndex[i]; #else int lightIndex = i; #endif vec3 lightPos = lcalcPosition(lightIndex) - viewPos; float lightDistance = length(lightPos); #if !@lightingMethodFFP if (lightDistance > lcalcRadius(lightIndex) * 2.0) continue; #endif float illumination = lcalcIllumination(lightIndex, lightDistance); float intensity = calcSpecIntensity(viewNormal, viewDir, shininess, normalize(lightPos)); specularLight += lcalcSpecular(lightIndex).xyz * intensity * illumination; } return specularLight; } #endif