Need some help with sky light lighting

Hello everyone, I am working on a level, which is inside of a building. The only apparent light source needs to be that of the sun, the problem is that when I am using just the sun, any areas with shadows are way too dark, so I dragged in a sky light. The sky light works perfectly to give me the right amount of brightness/visibility throughout the building, but areas that should be completely dark are still being lit (I have a few holes in the wall that should be dark. What is the best way to have good indirect lighting from a sky light in part of my level, but keep enclosed areas dark?

Edit: If there is another way to force these holes to be dark, but still look natural (They should be dark regardless of lighting), I would like to know a solution for that as well.

You can try using DFAO to get ambient occlusion from the skylight but IMO it doesn’t work very well.

You can also try using negative lights to “cast” shadows in these areas but it’s unreliable and produces shadowing artifacts if dynamic objects enter the space.

You could obviously try having your static skylight cast shadows but this means it does very little “global” brightening since a building is enclosed on all sides…

I once requested a volume which enables the user to manually increase or decrease lighting brightness in an area, Epic didn’t go for it but maybe with more requests they’d consider it, as this does seem like a common problem (for example, outdoor levels with caves also suffer from this issue).

Actually, I came up with a solution for this problem (though it does require a postprocess material) which is somewhat complicated but works quite well for me. Now, admittedly, I’m using a cel-shaded game, so I can get away with some stark darkness that maybe doesn’t work for your game, but if you want to give it a shot, go ahead.

First, you need to create a material called “shadowmask” or something, which is set to be a decal which ONLY blends Normal. What you want to do is connect two constants; 1 to opacity (or I suppose you could use some sort of feathering mask if it works better for you), and 0 to Normal.

The reason this effect works is that all normals in a standard game are unit vectors; they indicate a direction but their length is always 1. For a normal to have a length value of 0,0,0, it HAS to be specified manually, for example by placing the decal we just created.

Next, you configure your postprocess material like so (note that this is a screengrab of mine, so it has a Lerp node you don’t need; if you don’t have a postprocess material already, just grab PostProcess Input 0 and place it where my Lerp node is. Otherwise, you should be replacing my Lerp node with whatever you were currently feeding to your postprocess emissive output). Note that if you want emissives to shine through the brightness, you’ll need to calculate just the emissive; I use Postprocess Input 0 minus BaseColor, and then subtract 0.5 and multiply the result by 2; this makes sure that only supercharged emissive color in the scene (i.e. that which is much larger than a value of 1; my emissive materials use 8 or 10 values) isn’t black, and this is then added to the black that the postprocess generates to feed emissive through the shadows.


The net result is this; I can place a decal and it will “cast a shadow”, regardless of lighting. Note that in my case I WANT the shadow to be pitch black; you could just do some simple math to make the 0-1 multiplier which we connect to our main scene be, for example, a 0.15-1 multiplier or something, so that there’s SOME amount of light in the scene in the shadowed regions. Note that using decals in this way (as volumetric stains) isn’t exactly supported; the X axis of the decal actor automatically comes with a lerp-out curve, so if you want hard edges, you’ll need to layer a few decals; a large one with a soft curve to cover most of the space, and then one or two smaller ones at the edges to help blacken the space where the larger decal tapers out.