Sky, Atmosphere, and Night Sky



Since update 0.39, BeamNG uses a new sky and atmosphere pipeline for outdoor lighting. It provides the main lighting context for a level: sun and moon light, atmospheric sky color, directional ambient light, cloud transmittance, fog interaction, stars, the Milky Way, constellations, meteors, and optional sky profiles.

In current levels this is usually built from:

  • TimeOfDay - level clock, seasonal sun position, observer location, date, and optional profile selection.
  • ScatterSky - atmospheric sky rendering, sky ambient, night-sky rendering, and sky art controls.
  • CloudLayer - cloud cover and cloud transmittance that affect sky lighting.
  • LevelInfo - level-wide fog density, visible distance, environment map, and related level settings.
  • core_celestial - runtime system that reads TimeOfDay and pushes the live sun, moon, stars, meteors, and profile data into ScatterSky.

If you are setting up a level

For a normal outdoor level, start simple:

  1. Add one TimeOfDay, one ScatterSky, one CloudLayer, and one LevelInfo.
  2. Set TimeOfDay.time / startTime for the initial local time.
  3. Set latitude, longitude, year, month, day, and utcOffset if the sky should match a real place and date.
  4. Use the stock Earth sky first. Add a celestialProfile or level-local celestial.json only when you need a custom atmosphere or extra bodies.
  5. Tune fog amount with LevelInfo.fogDensity / fogAtmosphereHeight, clouds with CloudLayer, and sky look with the atmosphere/profile values.

Most levels should not need script-driven bodies, custom curves, or debug overlays.

For users and modders

The authored sky data is the same across graphics presets, but some settings change how much of it is visible or how accurately it contributes to lighting:

  • Cloud quality affects cloud sampling, cloud transmittance, and how clouds influence sky ambient lighting.
  • Lighting Quality and Shadow Quality affect shadow filtering and penumbra behavior, especially for sun shadows.
  • Exposure, tone mapping, HDR output, and local exposure affect how bright the sky, moon, stars, clouds, and fog appear.

When testing level lighting, check the intended quality preset first, then verify that the level still reads well on lower presets.

Current sky pipeline

Starting with update 0.39, the sky pipeline is physically based. The sky is evaluated into lookup textures and directional ambient data, then used by scene lighting, fog, clouds, reflections, and exposure.

TimeOfDay is the source of the level’s clock, place, and date. The celestial runtime reads that data just before rendering and updates ScatterSky with the current sun, moon, star field, meteor shower state, and optional profile atmosphere. ScatterSky no longer needs to listen directly to TimeOfDay; this avoids two systems fighting over the same sky positions.

Default values in this system are calibrated around physically correct brightness. The sun, moon, stars, Milky Way, meteors, atmospheric sky, and related exposure response are intended to start from real-world scale, with artistic controls acting as offsets from that baseline.

For artists and modders, sky lighting is no longer just a flat color:

  • Sun and moon direction affect direct light.
  • The atmosphere affects sky color, horizon color, and atmospheric fog color.
  • The sky contributes directional ambient lighting through SH9 data.
  • Clouds can affect sun transmittance and sky ambient lighting.
  • Exposure and tone mapping decide how the final sky brightness appears on screen.

How the sky is simulated

The daytime sky is generated from an atmosphere model rather than from a painted sky color. Sunlight enters the atmosphere, is scattered by air molecules, aerosols, and absorption layers, and is evaluated into a small set of lookup textures. These lookup textures let the renderer reuse expensive atmosphere integration for the visible sky, sun transmittance, aerial perspective, fog, and ambient lighting.

The current sky pass builds these results in stages:

  • Transmittance LUT - stores how much sunlight survives along paths through the atmosphere. It is used for sun color, sun brightness, and atmospheric attenuation.
  • Multiscatter LUT - approximates light that has scattered more than once through the atmosphere. This keeps the sky from looking too dark or thin, especially near the horizon, in haze, and around low sun angles.
  • Camera volume - stores view-dependent aerial perspective around the camera. Other rendering paths can use it so distant objects, fog, and sky lighting agree.
  • Sky-view LUT - stores the final sky radiance for the current view and sun direction. The visible sky shader samples this and adds the sun disc, night sky, and height fog.

The main atmosphere controls are:

  • Rayleigh scattering, which is the small-particle air scattering that makes clear daytime skies blue and gives low sun angles stronger red/orange color shifts.
  • Mie scattering and extinction, which represent larger particles such as haze and aerosols. These mostly affect the sun glow, horizon haze, and the softness/brightness around the sun.
  • Absorption, including ozone absorption, which changes which wavelengths survive through long atmospheric paths.
  • Planet radius, atmosphere height, ground albedo, solar irradiance, and sun angular size, which define the physical scale and brightness baseline.

Single scattering is the direct contribution from sunlight scattering once toward the camera. Multiscattering is the extra contribution from light that bounces through the atmosphere multiple times before reaching the camera. Without multiscattering, skies tend to lose too much energy and can look unnaturally dark in hazy or low-angle lighting. In BeamNG this is handled by the multiscatter LUT and reused by the sky-view and camera-volume passes.

At render time the sky result is not only drawn behind the level. It also drives the outdoor lighting context. Direct sun and moon light come from their current directions, ambient sky lighting is stored as SH9 directional data, clouds can reduce sun and sky transmittance, and fog uses the same atmospheric color basis so it follows the current time of day.

Outdoor ambient lighting is computed separately from the visible sky by sampling the sky into SH9 data. When volumetric clouds are active, those samples can trace through the cloud layer, so cloud coverage can affect both the visible sky and the ambient light received by level objects. The same process also calculates sun transmittance at the current view position for consistent sunlight attenuation.

Shadow maps, PCSS, screen-space shadows, and GTAO+ determine where direct and ambient sky light reaches scene surfaces. See Lighting Techniques for how these methods work together.

Celestial motion, phases, and eclipses

The celestial runtime uses TimeOfDay’s local clock, latitude, longitude, date, and UTC offset to place the sun, moon, stars, and meteor showers. This means two levels with the same clock time can still have different skies if they use different locations, dates, or time zones.

The moon is rendered as a lit body. Its position, lit fraction, and light contribution are driven by the astronomical runtime. A full moon has a high moonIllumination value and can contribute night light, while a new moon has little visible lit surface and much less moonlight. The disc shader uses the direction to the sun to place the terminator, with optional earthshine and artistic EV offsets for readability.

Solar eclipses happen when the moon passes close enough to the sun in the sky that the two discs overlap from the level’s observer position. The runtime can search for the next solar eclipse visible from the level’s TimeOfDay latitude and longitude. During rendering, the directional sun brightness is reduced when the moon disc overlaps the sun disc, based on their angular sizes and separation.

This is intentionally a sky and lighting simulation, not a full scientific eclipse renderer. It gives the correct authoring relationship: an eclipse depends on the level’s place, date, time, moon position, and sun position. If those values are changed, the apparent eclipse timing and strength change with them.

TimeOfDay and astronomical data

TimeOfDay controls the normalized local day time and stores observer information used by the current astronomical sky:

Field Meaning
time / startTime Normalized local civil day. 0 is local noon, 0.25 is evening, 0.5 is midnight, and 0.75 is morning.
play Whether time advances automatically.
dayLength Real seconds per full virtual day.
latitude Observer latitude in degrees north.
longitude Observer longitude in degrees east.
year, month, day UTC calendar date for real sky positions.
utcOffset Optional dynamic field for exact civil UTC offset in hours, including DST.
dstRule Optional dynamic field: auto, eu, us, au, or none.
celestialProfile Optional dynamic field selecting a sky profile, such as earth or a direct JSON path.

Latitude, longitude, date, and UTC offset affect the sun, moon, stars, constellation orientation, and meteor shower schedule. Use them when a level should have a believable real-world sky.

If the stars or constellations look mirrored east-west for a level’s world axes, adjust ScatterSky.starAzimuthSign.

ScatterSky in the current sky path

ScatterSky is still the main sky object, but in the update 0.39 sky path the active controls are the sky LUT atmosphere fields, celestial runtime fields, cloud transmittance, exposure, and debug/customization fields.

Older ScatterSky fields may still appear in saved level files, but this page only covers the current authoring controls.

Only azimuth and elevation are networked fields on ScatterSky. For full changes to other fields, apply the object changes through the editor or reload/update the level object.

Current atmosphere fields include:

Group Useful fields
Rayleigh atmoRayleighScattering, atmoRayleighScaleHeight
Mie/aerosols atmoMieScattering, atmoMieExtinction, atmoMieScaleHeight, atmoMiePhaseG
Absorption atmoAbsorption, atmoOzoneLayerWidth, atmoOzoneConst0, atmoOzoneLinear0, atmoOzoneConst1, atmoOzoneLinear1
Planet/solar atmoPlanetRadius, atmoThickness, atmoSunIrradiance, atmoSunAngularSize, atmoGroundAlbedo
Profile look skyBrightness, exposure

Advanced celestial customization

The celestial runtime adds several customization paths on top of the stock Earth sky. These are mostly for experienced modders, tools, and unusual skies:

Feature Options
Profile selection TimeOfDay.celestialProfile, level-local celestial.json, core_celestial.loadProfile(pathOrTable)
Runtime driver core_celestial.setDriver(fn) to override the per-frame sun, bodies, star orientation, and meteor state
Extra bodies Profile bodies[], or script-driven bodies through setCelestialBodies
Day/night response curves setCelestialCurve(skyId, index, points)
Celestial picking pickCelestial for debug/hover tools

setCelestialBodies bodies support:

Field Use
azimuth, elevation Body position in sky coordinates.
angularSize Apparent diameter in degrees.
illumination Lit fraction for phase rendering.
brightnessEV Artistic brightness offset in EV/stops.
emissive Self-lit disc, useful for extra suns or stars.
toSun Direction the body is lit from.
tint RGB color multiplier.
albedo Texture path for the body surface.

setCelestialCurve has five curve slots. Use these only when a normal sky profile is not enough:

Index Curve
0 Night interpolant.
1 Sun disc / Mie response.
2 Directional light brightness.
3 Day/night color blend.
4 Moon/night tint.

Sky profiles

Sky profiles are JSON presets loaded by core_celestial. They are the preferred way to package atmosphere settings for a level or mod.

Profiles are resolved in this order:

  1. TimeOfDay.celestialProfile, if set.
  2. A level-local celestial.json next to the loaded mission file.
  3. No profile, which leaves the built-in Earth defaults active.

If celestialProfile is a bare name, it resolves to /art/skies/profiles/<name>.json. For example, earth loads /art/skies/profiles/earth.json. It can also be a direct path such as /levels/my_level/celestial.json.

The stock profiles are:

Profile Path Use
earth /art/skies/profiles/earth.json Documents the default Earth-like sky values. Loading it should not visibly change a normal level.
mars /art/skies/profiles/mars.json Non-Earth atmosphere preset. Useful as a reference, but start custom level work from Earth unless you intentionally need another planet.

Minimal Earth-based profile shape:

{
  "name": "my_sky",
  "atmosphere": {
    "planetRadiusKm": 6360,
    "atmosphereHeightKm": 100,
    "rayleighScattering": [0.005802, 0.013558, 0.0331],
    "rayleighScaleHeightKm": 8,
    "mieScattering": [0.003996, 0.003996, 0.003996],
    "mieExtinction": [0.00444, 0.00444, 0.00444],
    "mieScaleHeightKm": 1.2,
    "miePhaseG": 0.8,
    "ozoneAbsorption": [0.00065, 0.001881, 0.000085],
    "groundAlbedo": [0, 0, 0],
    "solarIrradiance": [100000, 100000, 100000],
    "sunAngularSizeDeg": 0.2525
  }
}

Profiles can also define moonAlbedo and extra bodies. Extra bodies may use fixed azimuth / elevation, or simple equatorial motion with ra0, dec, and periodH. Body fields include angularSize, illumination, brightnessEV, emissive, toSun, albedo, and tint.

For script-driven experiments, core_celestial.loadProfile(pathOrTable) replaces the active profile at runtime, and core_celestial.setDriver(fn) can override the per-frame sun, bodies, stars, and meteor state.

Night sky

Since update 0.39, the procedural astronomical night sky is the normal path for levels.

It renders:

  • Stars from the baked star catalog.
  • The Milky Way.
  • The moon disc and moonlight.
  • Meteor showers and sporadic meteors.
  • Optional constellation lines and constellation names.

Night sky Night sky

Moon controls

The moon is rendered as a lit, data-driven body and also contributes night lighting. Its position and phase are driven by the astronomical system introduced with the update 0.39 sky path.

Useful author-facing fields:

Field Use
moonEnabled Legacy single-moon render toggle. In the current celestial path, the moon is normally pushed as a data-driven body.
moonAngularSize Apparent angular size of the moon disc.
moonAlbedo Near-side moon albedo texture.
moonBrightnessEV Artistic brightness offset in EV/stops.
moonEarthshine Faint glow on the unlit side.
moonShadowFloor Ambient floor for the shadowed side.
moonLimbDarkening Darkening toward the moon edge.
moonTerminatorSoftness Softness of the lit/unlit phase edge.
moonGlow Atmospheric glow around the moon.
moonFlatten Vertical squash for atmospheric or artistic shape.
moonLightColor Color of the night directional light.
moonIllumination Runtime lit fraction, driven by core_celestial.
moonOrbitNodeRad Runtime lunar node used by the moon-path overlay.

EV fields use stops: 0 means the calibrated value, +1 doubles brightness, and -1 halves it.

The default value of 0 should be treated as the physically calibrated baseline. Increase or decrease EV values only when the level needs an artistic readability adjustment.

The moon disc also uses emissive EV compression at night so high exposure does not immediately clip its details. moonAzimuth, moonElevation, and moonIllumination are runtime-driven and should not be authored as fixed level values.

Stars, Milky Way, and meteors

These controls are artistic offsets on top of calibrated ranges. Use them for readability, not as a substitute for exposure.

Group Useful fields
Stars starsEnabled, starCatalog, starSizeScale, starExtinction, starBrightnessEV, starDensity, starHaze, starColorVariation, starNorthOffset, starAzimuthSign, starPulse
Runtime stars starLocalSiderealTime, starLatitude, starVisibility
Milky Way milkyWayEnabled, milkyWayBrightnessEV, milkyWayCore, milkyWayDust, milkyWayWidth, milkyWayWarmth, milkyWayDustScale, milkyWayGalacticX/Y/Z, milkyWayDebug
Meteors meteorsEnabled, meteorBrightnessEV, meteorTrailLength, meteorWidth, meteorSpeed, meteorInject
Runtime meteors meteorRate, meteorShowerFraction, meteorRadiantRA, meteorRadiantDec

Meteor rate, shower fraction, radiant, star visibility, local sidereal time, latitude, and moon illumination are runtime-driven by the astronomical system. Do not author those as fixed level values unless you are building a specific scripted setup.

Major meteor showers are date-driven. The runtime currently models Quadrantids, Lyrids, Eta Aquariids, Perseids, Orionids, Leonids, and Geminids, plus a low sporadic baseline outside shower peaks.

Default baked data paths are /art/skies/stars/catalog.bin, /art/skies/stars/constellations.bin, and /art/skies/stars/constellation_labels.bin. These are generated by the celestial bake tools and should normally be reused by levels.

Constellations

Constellation lines and names are part of the update 0.39 night-sky system. They are rendered from baked data and localized names.

Useful fields:

Field Use
constellationsEnabled Draw constellation line figures.
constellationLines Baked constellation line data.
constellationBrightness Line brightness.
constellationThickness Line thickness in pixels.
constellationColor Line tint.
constellationNamesEnabled Draw localized constellation labels.
constellationLabels Baked label anchor data.
constellationNameBrightness Label brightness/opacity.
constellationNameScale Label size scale.
constellationNameColor Label tint.

Constellation names are normally pushed by the runtime from localized translation keys. Do not edit constellationNames manually for normal level authoring.

Debug overlays

ScatterSky includes optional celestial overlays for debug use:

Field Use
gridEnabled Alt/azimuth grid and cardinal markers.
gridBrightness Grid brightness.
gridThickness Grid line thickness in pixels.
gridColor Grid tint.
equatorialGridEnabled RA/Dec grid, celestial equator, and ecliptic.
meridianEnabled North-zenith-south meridian and zenith marker.
moonPathEnabled Date-driven moon orbital path.

Keep these disabled for normal gameplay content.

Clouds, fog, and ambient light

The sky pipeline feeds directional ambient lighting and fog. The update 0.39 volumetric cloud path can also influence ambient lighting and sun transmittance.

The current cloud path is volumetric. Instead of drawing only a flat cloud texture on a dome, the renderer ray-marches through a cloud layer around the camera and integrates cloud density, lighting, and transmittance along the view ray. This lets clouds have depth, soft edges, internal lighting, and changing opacity when viewed from different angles.

Cloud shape is built from several inputs:

  • A generated 2D weather map controls large-scale coverage, precipitation/type data, and cloud type.
  • A 3D base noise volume creates the main cloud masses.
  • A smaller 3D detail noise volume erodes cloud edges and adds high-frequency breakup.
  • A height gradient shapes the vertical profile into stratus, stratocumulus, or cumulus-like forms depending on the weather map.
  • Wind offsets move the weather and noise samples over time.
  • A separate thin cirrus layer can add high, wispy cloud contribution.

Cloud lighting uses the current sun direction, sun irradiance, and sky ambient SH9 data. Direct sunlight is attenuated by cloud density along the path toward the sun, while ambient light fills shadowed cloud areas from the sky. The cloud shader also uses phase functions, powder edge brightening, and an internal multiscattering approximation so dense clouds keep believable brightness instead of becoming flat gray volumes.

Cloud transmittance is used outside the cloud draw pass too. The renderer produces cloud shadow/transmittance data for sunlight and samples clouds while building sky ambient SH9. This is why changing cloud coverage can affect sun strength, ambient lighting in shadows, fog consistency, and lens flare/cloud occlusion, not only the visible cloud shapes.

Important relationships:

  • CloudLayer.coverage, windSpeed, windDirection, and altitudeKm feed the current volumetric cloud path.
  • coverage changes the large-scale cloud amount. Higher values create more filled weather-map regions and also increase the thin cirrus contribution.
  • windSpeed and windDirection move the cloud noise/weather pattern over time.
  • altitudeKm sets the base altitude of the main volumetric cloud layer.
  • Older CloudLayer fields may still exist in saved data, but they are not useful controls for the current volumetric cloud path.
  • LevelInfo still controls fog density, atmosphere height, and visible distance.
  • The current atmospheric sky controls sky-derived fog color.
  • Cloud quality settings affect ray-march sampling, reconstruction cost, and how often cloud shadow/transmittance data updates.
  • Auto Exposure and local exposure affect how sky, clouds, and fog appear on screen.

Check the sky with several cloud quality settings, times of day, and weather states before finalizing lighting.

Best practices

  • Use one primary TimeOfDay and one primary ScatterSky for normal outdoor levels.
  • Set latitude, longitude, date, and UTC offset when the real sky should matter.
  • Use celestialProfile or level-local celestial.json for custom atmosphere presets.
  • Tune exposure before deciding that the sky, stars, or moon are too bright or too dark.
  • Use EV brightness offsets sparingly; large offsets can break the calibrated relationship between sky elements.
  • Keep constellation overlays off unless the level intentionally needs them.

Related pages

External references

Last modified: July 23, 2026

Any further questions?

Join our discord
Our documentation is currently incomplete and undergoing active development. If you have any questions or feedback, please visit this forum thread.