<@if not DEFERRED_GLOBAL_LIGHT_SLH@> <@def DEFERRED_GLOBAL_LIGHT_SLH@> <@include DeferredLighting.slh@> struct SphericalHarmonics { vec4 L00; vec4 L1m1; vec4 L10; vec4 L11; vec4 L2m2; vec4 L2m1; vec4 L20; vec4 L21; vec4 L22; }; vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) { vec3 dir = direction.xzy; // we don;t understand why yet but we need to use z as vertical axis? const float C1 = 0.429043; const float C2 = 0.511664; const float C3 = 0.743125; const float C4 = 0.886227; const float C5 = 0.247708; vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) + C3 * sh.L20 * dir.z * dir.z + C4 * sh.L00 - C5 * sh.L20 + 2.0 * C1 * ( sh.L2m2 * dir.x * dir.y + sh.L21 * dir.x * dir.z + sh.L2m1 * dir.y * dir.z ) + 2.0 * C2 * ( sh.L11 * dir.x + sh.L1m1 * dir.y + sh.L10 * dir.z ) ; return value; } // Need one SH uniform SphericalHarmonics ambientSphere; // Everything about light <@include model/Light.slh@> // The view Matrix uniform mat4 invViewMat; vec3 evalAmbienGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { // Need the light now Light light = getLight(); vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); vec4 fragEyeVector = invViewMat * vec4(-position, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); vec3 color = diffuse.rgb * getLightColor(light) * getLightAmbientIntensity(light); vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); return color; } vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { // Need the light now Light light = getLight(); vec3 fragNormal = normalize(vec3(invViewMat * vec4(normal, 0.0))); vec4 fragEyeVector = invViewMat * vec4(-position, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); vec3 ambientNormal = fragNormal.xyz; vec3 color = diffuse.rgb * evalSphericalLight(ambientSphere, ambientNormal).xyz * getLightAmbientIntensity(light); vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); return color; } vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) { Light light = getLight(); vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); float diffuseDot = dot(fragNormal, -getLightDirection(light)); // need to catch normals perpendicular to the projection plane hence the magic number for the threshold // it should be just 0, but we have innacurracy so we need to overshoot const float PERPENDICULAR_THRESHOLD = -0.005; float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); //float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); // evaluate the shadow test but only relevant for light facing fragments float lightAttenuation = (1 - facingLight) + facingLight * shadowAttenuation; // diffuse light is the lightmap dimmed by shadow vec3 diffuseLight = lightAttenuation * lightmap; // ambient is a tiny percentage of the lightmap and only when in the shadow vec3 ambientLight = (1 - lightAttenuation) * lightmap * getLightAmbientIntensity(light); return diffuse * (ambientLight + diffuseLight); } <@endif@>