<@if not DEFERRED_GLOBAL_LIGHT_SLH@> <@def DEFERRED_GLOBAL_LIGHT_SLH@> <@include model/Light.slh@> <@include DeferredLighting.slh@> <@func declareSkyboxMap()@> // declareSkyboxMap uniform samplerCube skyboxMap; vec4 evalSkyboxLight(vec3 direction, float lod) { // textureQueryLevels is not available until #430, so we require explicit lod // float mipmapLevel = lod * textureQueryLevels(skyboxMap); return textureLod(skyboxMap, direction, lod); } <@endfunc@> <@func prepareGlobalLight()@> // prepareGlobalLight // Transform directions to worldspace vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); vec3 fragEyeVector = vec3(invViewMat * vec4(-position, 0.0)); vec3 fragEyeDir = normalize(fragEyeVector); // Get light Light light = getLight(); vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, vec3(metallic), roughness); color = vec3(albedo * shading.w + shading.rgb) * min(shadowAttenuation, obscurance) * getLightColor(light) * getLightIntensity(light); color += emissive; <@endfunc@> <@func declareEvalAmbientGlobalColor()@> vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 emissive, float roughness) { <$prepareGlobalLight()$> color += albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(light); return color; } <@endfunc@> <@func declareEvalAmbientSphereGlobalColor()@> vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 emissive, float roughness) { <$prepareGlobalLight()$> color += albedo * evalSphericalLight(getLightAmbientSphere(light), fragNormal).xyz * obscurance * getLightAmbientIntensity(light); return color; } <@endfunc@> <@func declareEvalSkyboxGlobalColor()@> <$declareSkyboxMap()$> vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 emissive, float roughness) { <$prepareGlobalLight()$> vec3 direction = -reflect(fragEyeDir, fragNormal); float lod = min(1.0 + floor((1.0 - gloss) * levels), levels); vec4 skyboxLight = evalSkyboxLight(direction, lod); color += albedo * skyboxLight.rgb * skyboxLight.a * obscurance * getLightAmbientIntensity(light); return color; } <@endfunc@> <@func declareEvalLightmappedColor()@> vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) { vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 diffuse, vec3 lightmap) { Light light = getLight(); // Catch normals perpendicular to the projection plane, hence the magic number for the threshold // It should be just 0, but we have inaccuracy so we overshoot const float PERPENDICULAR_THRESHOLD = -0.005; vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace float diffuseDot = dot(fragNormal, -getLightDirection(light)); float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); // Reevaluate the shadow attenuation for light facing fragments float lightAttenuation = (1 - facingLight) + facingLight * shadowAttenuation; // Diffuse light is the lightmap dimmed by shadow vec3 diffuseLight = lightAttenuation * lightmap; // Ambient light is the lightmap when in shadow vec3 ambientLight = (1 - lightAttenuation) * lightmap * getLightAmbientIntensity(light); return obscurance * albedo * (diffuseLight + ambientLight); } <@endfunc@> <@endif@>