Atmospheric fog colour material expression broken

The atmospheric fog colour material expression is broken in 4.12. I’m using it to light my scene so it looks extremely messed up right now.

This is an example of how I use it in a material:

In 4.11:

Same scene, sun position and fog settings in 4.12:

Note that in the 4.12 screenshot the sun setting is equivalent to “midday” but the sample colour is coming back black.

I’ve tried remaking the atmospheric fog and sunlight with no effect. I’ve also tried different sampling distances with no effect. It just seems to be broken and returning black.

Even the actual sky colour seems quite broken.

Exact same settings 4.12:
After a moment the sky refreshed in the editor and looked correct again, but the sample colour is still black.

Also: I’ve verified the engine and tried it in a new empty project. Same result.

Similar strange behavior happens with the Atmospheric Fog actor, as well as the material expression you mention in 4.12. To verify, just drop an Atmospheric Fog actor in an empty level in 4.11 and 4.12: In 4.12 there is visible banding across the horizon, which can be exaggerated by cranking up the Altitude Scale property of the actor from 1.0 to 1000.

I have traced the unwanted behavior in the AtmosphereCommon.usf shader file (source: Engine/Shaders/AtmosphereCommon.usf, in the release: c:/Program Files/Unreal Engine/4.12/Engine/Shaders/AtmosphereCommon.usf) in commit b9b38fe97bc4b403c2c7071a8130cf8e2e3c874e, which adds the abs() function to 4 places to guard against negative values before taking the square root.

In my testing, it is enough to replace the following lines in function GetAtmosphericFog(), around line 556:

   float Mu = (ViewPosition, V) / Radius;

    float T = -Radius * Mu - sqrt(abs(Radius * Radius * (Mu * Mu - 1.0) + RadiusGround * RadiusGround));

with these:

    float Mu = (ViewPosition, V) / Radius;
    float MuClamped = (Mu < 1.f) ? 1.f : Mu;

    float T = -Radius * Mu - sqrt(abs(Radius * Radius * (MuClamped * MuClamped - 1.0) + RadiusGround * RadiusGround));

Making that change and triggering a shader recompile (Ctrl+Shift+.) fixes the problem.

I can prepare a pull request, if required.

The inline if of MuClamped can be replaced by the more efficient max(1.f, Mu * Mu - 1.0) directly in the T calculation, and all other abs() calls too probably (didn’t check).

There appears to be a ticket in for this to be investigated already with UE-30844.


Thank you for the clearly written out information and changes that address this. I’ve added the notes to the ticket for this to be looked at more.

Thanks for your efforts, .

Heck, thanks for yours Jubanka!

I’ll run a custom build of the engine that addresses this for now until they can release the fix.

I’m not seeing the issue. Can it be added please? This is a world-ending bug for those of us using global lighting systems.

Hey ,

Stephen just added UE-30844 to the public bug tracker and I noticed it says “Backlogged”. The AtmosphericFog actor itself is broken in 4.12, place it in your level and the issue appears immediately without changing any settings. I’m a bit dumbfounded that such an important actor would be backlogged when there is a simple 2 line fix that can be done in a usf file posted above.

I have fixed it on my end for my project, but anyone who uses my community project will have to manually edit the usf file on their end too. I know from experience with a (optional) custom DOF shader file we added that not all users are comfortable editing/overwriting engine files, and I will end up getting a lot of complaints that my project is broken.

Could this fix please be added into 4.13? I will create a PR for it if it’s really necessary, it’s only 2 lines long.

Thanks for your help as always . =)

Do the PR, get the Engine Contributor badge. :slight_smile:

Good thinking, can never have enough badges!

Ok I just submitted it now, here’s the link to the PR:

Thanks, hope it can make it in by 4.13! =)


I removed the PR as I noticed the line I was editing (558) in AtmosphereCommon.usf (Release version) was modified recently on the branch. The line of code was changed from:

float T = -Radius * Mu - sqrt(abs(Radius * Radius * (Mu * Mu - 1.0) + RadiusGround * RadiusGround));

to (now line 565):

float T = -Radius * Mu - sqrt(Radius * Radius * (Mu * Mu - 1.0) + RadiusGround * RadiusGround);

I am not sure whether this is a change to fix this issue or if it is irrelevant. There have been a few changes to the file recently so I will build locally from to see if it has been fixed by an alternate method. If not I will re-open the Pull Request.

Will update asap.

Judging by the commit logs and changesets, the issue seems to be fixed both in and 4.13.

Good news!

I can confirm that this issue has been fixed in the branch, absolutely no issues with it anymore.

The changes made occurred before the recent branching of 4.13 (probably should have built that one instead), but I compared the shaders on Git and they are the same so it will be in 4.13.

Looks like the change was made for the Metal API, causing a regression from 4.11. The new code includes a #IF COMPILER_METAL check for the affected line/

Thank you guys! Sorry for my mini rant , was just a bit surprised by it. =)

EDIT: Should probably update UE-30488 when you guys have a chance!

For reference here is a link to CL #3063329 where the change occurred.

Thanks again.