Sky Atmosphere Transmittance Issue

The screenshots below show the UE Sky Atmosphere transmittance issue. All screenshots were taken in 4.27, but I ran into the same problem in newer 5.1 and 5.2 versions of the engine.

  1. there is no mesh behind the atmosphere, and the color of the solar disk is correctly calculated by the Sky Atmosphere actor, taking into account atmospheric transmittance;

  2. atmosphere is surrounded by a mesh with the unlit material which renders the stars and the solar disk and also calculates the atmospheric transmittance using the custom expression (see below), so the solar disk looks roughly the same as in the first screenshot;

  3. atmosphere is surrounded by the mesh with the same material, but the atmospheric transmittance calculation is disabled in the material, resulting in an unnaturally bright solar disk, which means that the color of this material (in this case, its emissive color) is not correctly attenuated by the Sky Atmosphere actor;

In the case of the solar disk, the correct result can also be achieved with the SkyAtmosphereLightDiskLuminance material expression. But there doesn’t seem to be a standard (documented) way to get the correct colors of an arbitrary celestial body when viewed through the atmosphere, like in the following screenshots:

  1. the setup is the same as in the screenshot #2, but now the material renders accretion disk of a black hole instead of the solar disk; the atmospheric transmittance calculation is enabled in the material;

  2. the same setup as in the previous screenshot but the atmospheric transmittance calculation is disabled in the material;

More screenshots

In the screenshots #2 and #4 the atmospheric transmittance is calculated in the material using the GetAtmosphereTransmittance function, which returns a vector (float3), so both the luminance and chromaticity of the material is affected by the atmosphere. In contrast, the SkyAtmosphereAerialPerspective material expression outputs transmittance as a scalar value. The Is Sky flag is disabled in all materials shown, and the following console commands were executed:

  • r.SkyAtmosphere.FastSkyLUT 0
  • r.SkyAtmosphere.AerialPerspectiveLUT.FastApplyOnOpaque 0

The custom expression using the GetAtmosphereTransmittance function is based on the functions found in the files DeferredLightPixelShaders.usf, BasePassPixelShader.usf, SkyAtmosphereCommon.ush.

Custom expression for UE 4.27:

#include "/Engine/Private/SkyAtmosphereCommon.ush"

// Material Node Inputs {expected_type input_name}:
// float3 pos;
// float3 dir;

const float3 PlanetCenterToWorldPos = (pos - View.SkyPlanetCenterAndViewHeight.xyz) * CM_TO_SKY_UNIT;

float3 atmosphereTransmittance = GetAtmosphereTransmittance
(
    PlanetCenterToWorldPos, 
    dir, 
    View.SkyAtmosphereBottomRadiusKm, 
    View.SkyAtmosphereTopRadiusKm,
    View.TransmittanceLutTexture, 
    View.TransmittanceLutTextureSampler
);

return atmosphereTransmittance;

Custom expression for UE 5.0 - 5.2:

#include "/Engine/Private/SkyAtmosphereCommon.ush"

// Material Node Inputs {expected_type input_name}:
// FLWCVector3 pos;
// float3 dir;

// note that this expression uses the LWCpos variable of type FLWCVector3;
// in the generated HLSL code for this custom expression, 
// the LWCpos variable is provided along with the float3 variable pos 
// if the "pos" input of this custom expression (custom material node) is connected 
// to a material node which outputs a FLWCVector3 value (e.g. AbsoluteWorldPosition)
const float3 PlanetCenterToTranslatedWorldPos = 
(LWCToFloat(LWCAdd(LWCpos, ResolvedView.PreViewTranslation)) - ResolvedView.SkyPlanetTranslatedWorldCenterAndViewHeight.xyz) * CM_TO_SKY_UNIT;

float3 atmosphereTransmittance = GetAtmosphereTransmittance
(
    PlanetCenterToTranslatedWorldPos, 
    dir, 
    ResolvedView.SkyAtmosphereBottomRadiusKm, 
    ResolvedView.SkyAtmosphereTopRadiusKm,
    View.TransmittanceLutTexture, 
    View.TransmittanceLutTextureSampler
);

return atmosphereTransmittance;

I’m not sure if using the GetAtmosphereTransmittance function is the intended way to calculate atmospheric transmittance, but it gives correct results without noticeable performance impact. Perhaps there is some setting to get correct (accurate) transmittance, like the Per Pixel Atmosphere Transmittance in the directional light. In overall, it is not clear whether the way in which the atmospheric transmittance is calculated in the Sky Atmosphere actor is by design or if it is some sort of bug.

1 Like