The Night Sky

The sky of The Sky, Day and Night is physically based at night as well as by day, after Jensen et al., “A Physically-Based Night Sky Model” (SIGGRAPH 2001). It shows the real stars where they stand for the date, the hour and the latitude, the Milky Way, the zodiacal light, the airglow, light pollution and a moon with its real face. All of it comes with Environment; there is nothing to set up.

Orion over the southern horizon on a dark January night, with Sirius below it and Procyon to the left.

Orion due south at 45 degrees north, 22:00 on 15 January. Betelgeuse is orange and Rigel blue-white: each star has the colour of its B-V index.

The Milky Way rising from the southern horizon on a July night, split by a dark dust lane.

The core of the Milky Way in Sagittarius, low in the south on a July night at 45 degrees north, with the Great Rift splitting it.

What is in it

Every part is a radiance in the scene’s light units, calibrated against the full moon (Look.moon_illuminance is magnitude -12.74), so their ratios are the real ones.

Stars. The 9096 stars of the Yale Bright Star Catalogue (BSC5), down to about magnitude 7. Each star is a point of light one pixel wide that holds the star’s whole light: it does not shimmer or alias when the view turns, and its brightness follows its magnitude. A star too bright for the display grows a little instead of clipping, so Sirius still reads brighter than Polaris. The colour is a blackbody’s at the temperature its B-V index gives. The air dims the stars towards the horizon (through the atmosphere’s transmittance, that is, the airmass), and they twinkle more there, in colour near the horizon. Only the stars brighter than the limiting magnitude of the sky behind them show: about 6.5 on a dark site, about 4 under a full moon or in a suburb, about 3 in a city.

Constellations for the date. The star sphere turns with the local sidereal time and is precessed from the catalogue’s J2000 positions to the date (the IAU 1976 angles), so the constellations stand right for any date, hour and latitude. Nutation (under 20 arc seconds), aberration and the stars’ proper motions are left out.

The Milky Way. A brightness map in galactic coordinates, 512 x 256, made by a procedural model: the disc, the bulge towards Sagittarius, the star clouds of Scutum, Cygnus and Carina, the Great Rift and other dust lanes, the Coalsack and the Magellanic Clouds. The bulge is warmer than the disc.

Zodiacal light. Sunlight scattered by the dust between the planets: a cone along the ecliptic, brightest near the sun after dusk and before dawn, with the faint gegenschein opposite the sun.

Airglow. The upper atmosphere’s own faint glow, mostly the green oxygen line, brighter towards the horizon and drifting in slow bands.

Light pollution. Look.light_pollution from 0 (a dark site) to 1 (a city centre), in Look.light_pollution_color, brightest near the horizon. It washes out the Milky Way and the fainter stars.

The same July sky twice: on the left the Milky Way over a dark site, on the right a brown glow with almost no stars.

Look(light_pollution=0.0) and Look(light_pollution=0.6).

The moon. Its face comes from NASA’s CGI Moon Kit (the Lunar Reconnaissance Orbiter’s colour mosaic, reduced to 256 x 128), turned so the near side faces the earth and north points to the ecliptic pole (libration is ignored). The sun lights it with a Lommel-Seeliger surface and an opposition surge, so a full moon is bright out to the limb and brightens sharply at full. Earthshine lights the dark side, most on a thin crescent.

Three views of the moon: a waxing half moon, the full moon showing its maria, and a waning half moon.

The moon at first quarter, full and last quarter, seen from 45 degrees north.

The moon’s light on the world follows the same phase law (Allen’s): a half moon gives about a tenth of the full moon’s light, not half of it. The light’s colour is sunlight reddened by the moon’s albedo. The blue of a moonlit night is in the eye, not in the light: Look.moon_tint (for example (0.88, 0.95, 1.2)) gives it, or purkinje() from common.glsl in a post pass.

A full moon high over a dark field with a tree, and only a few bright stars.

A full moon at 21:00 on 3 January. The moonlit sky leaves only the brightest stars.

On a screen

A dark-adapted eye sees a moonless sky far brighter than a moonlit night’s exposure would show it. The frame’s exposure already follows the night’s light on the ground part of the way (Look.adaptation, The Sky, Day and Night); on top of it the glow (Milky Way, zodiacal light, airglow, light pollution) and the stars are brightened by an adaptation gain, tuned at a moonlit exposure (the exposure’s rise beyond that is divided out of it, the NIGHT.w frame value, so the sky does not brighten twice). The gain is largest on a dark night and falls towards 1 as the sky overhead brightens with the moon, twilight or a city. The environment probe sees the night sky without the gains: it is light on the world, and starlight and airglow light the ground at their physical level. The faint glow loses its colour to the eye’s night vision (the display’s rod shift, applied once to the whole picture). The moon’s disc is about a thousand times brighter than the moonlit sky; it is shown at its own exposure, with its maria and phases intact. Physics sets every ratio within each part; the gains only set how the night reads.

The look fields

Field

Default

What it does

stars

1.0

star brightness

twinkle

0.5

scintillation

milky_way

1.0

Milky Way brightness

zodiacal_light

1.0

zodiacal light brightness

airglow

1.0

airglow brightness

light_pollution

0.0

0 a dark site .. 1 a city

light_pollution_color

(1, 0.72, 0.45)

the glow’s colour

moon_tint

(1, 1, 1)

times the moon’s light colour

earthshine

0.02

the moon’s dark side

They blend like every other field, so a weather look or an hour key can change them:

from acron.sky import Environment, DayClock, Look

clock = DayClock(latitude=45.0, longitude=15.0, utc_offset=1.0)
clock.set_date(2026, 1, 15, 22.0)
env = Environment(base, clock=clock, look=Look(light_pollution=0.3))
env.set_look(env.base_look.replace(light_pollution=0.0), seconds=20)

The catalogue in Python

acron.sky.stars reads the catalogue for gameplay or tools, with no engine and no numpy:

from acron.sky import sky_at
from acron.sky.stars import load_catalogue

stars = load_catalogue()                  # brightest first
sirius = stars.find(2491)                 # by Harvard Revised number
where = sky_at(clock).star_direction(sirius.ra, sirius.dec)
print(where[2] > 0.0)                     # is Sirius up?

It also has magnitude_to_flux, star_color (from B-V), precession_matrix and to_galactic. Sky has moon_phase_angle and moon_brightness (the phase law) beside moon_phase (the lit fraction), and from_equatorial / to_equatorial for the star sphere.

The data

The three data files live in acron/sky/data/ with the scripts that made them:

  • stars.bin (91 KB): the Yale Bright Star Catalogue, 5th revised edition (Hoffleit and Warren, 1991), from the CDS (catalogue V/50). For each star it holds the right ascension, declination, V magnitude, B-V and HR number. build_stars.py downloads the catalogue and checks its checksum.

  • moon.bin (33 KB): NASA Scientific Visualization Studio, CGI Moon Kit (2019), from LRO camera data; public domain. Made by build_moon.py.

  • milky_way.bin (27 KB): the procedural model in build_milky_way.py; no outside data.

Known limitations

  • The ground is lit by the moon, not by starlight and airglow: a moonless landscape is black.

  • Planets are not drawn, and neither are comets or meteors.

  • The moon does not librate or show its parallax (under a degree).

  • The Milky Way is a model, not a survey: its shape is right and its details are invented.

  • The star grid is per pixel. A pixel under a dense patch of the Milky Way loops over up to 48 stars, at night only.

References

  • Henrik Wann Jensen, Frédo Durand, Michael Stark, Simon Premože, Julie Dorsey and Peter Shirley, “A Physically-Based Night Sky Model”, SIGGRAPH 2001.

  • Dorrit Hoffleit and Wayne Warren, The Bright Star Catalogue, 5th revised edition, Yale University Observatory, 1991.

  • Christian Leinert et al., “The 1997 reference of diffuse night sky brightness”, Astronomy and Astrophysics Supplement 127, 1998.

  • Bradley Schaefer, “Telescopic limiting magnitudes”, PASP 102, 1990.

  • Jay Lieske et al., “Expressions for the precession quantities”, Astronomy and Astrophysics 58, 1977.

  • Clabon Allen, Astrophysical Quantities, 3rd edition, 1976 (the moon’s phase law).

  • Ballesteros, “New insights into black bodies”, EPL 97, 2012 (B-V to temperature).