notes on machines

The Same Sky, Twenty Years Later

The previous post took apart the sky in EverQuest’s 2005 client: a thirty-two pixel square image, six passes, and an opaque dome doing the culling. The whole thing is arithmetic you could do on paper.

The obvious question is what you would build instead now, and the obvious answer — “a physically based atmosphere” — turns out to be less than half of it. Two of the things that sky does have no modern replacement because they were never approximations in the first place. One of them is an art direction decision, and if you replace it with physics you get something correct and worse.

So this is the same feature list, built the way you would build it today, with the parts that should survive kept deliberately rather than by accident. Everything below is computed in this page, from parameters written down in the module that uses them.

The ramp becomes an integral

EverQuest’s dome samples a painted gradient. A modern sky integrates along the view ray: how much air is between you and space, what it scatters, and what colour it scatters it.

Three terms do almost all the work. Rayleigh scattering off air molecules, which goes as roughly the inverse fourth power of wavelength — (5.8, 13.6, 33.1) per thousand per kilometre, blue nearly six times red, and that ratio is the reason the sky is blue and the sunset is not. Mie scattering off aerosols, which is grey and sharply forward-biased, and is the haze and the glow around the sun. And ozone, which absorbs in the middle of the band and barely at all in the blue.

Ozone is the one that earns its keep. Drop it and twilight goes grey-brown as the Rayleigh term thins out; keep it and the zenith stays blue after the sun is down, which is what actual dusk looks like.

Both skies, side by side

Here is the thing I did not expect to find when setting this up.

It would be easy to frame the comparison as one dimension against two — the painted ramp reads a single row, the atmosphere is a function of the whole hemisphere. That framing is wrong, and it is wrong in EverQuest’s favour. The dome rotates so its pole is the sun, so its ramp is indexed by the angle from the sun rather than by elevation. To first order that is exactly the right coordinate: the Rayleigh phase term is a function of that angle, which is why the real sky is darkest about ninety degrees away from the sun.

So both halves below are painted from the same quantity. What is left over is the interesting part.

EverQuest — a painted ramp, aimed at the sun horizon computed, graded 75% toward the ColorMap horizon sun 6° above the horizon · ColorMap bound at hour 06.0 · auto-exposure x15 Luminance from the atmosphere, chroma from the palette: the dawn stays as orange as it was painted, and the horizon band it could never express is underneath it. Grading cannot move brightness — which is what leaves the day/night cycle to the exposure alone.
6°
06.0
75%
The same sky painted two ways, at a low sun. Enable WebAssembly to move the sun, change which ColorMap is bound, and grade the computed half toward it.

The disagreement is the horizon, and it is structural rather than a matter of tuning. Angle-from-the-sun cannot know how much air a ray passes through, so an authored ramp is perfectly symmetric about the sun — the same texel forty degrees away in every direction. The real sky is not symmetric, because near the horizon you are looking through far more atmosphere. It brightens into a band all the way round the rim.

No amount of repainting fixes that. It is not a colour that is missing, it is a coordinate.

Keeping the dawn

Here is where you would go wrong by finishing too early.

EverQuest’s dawn ColorMap is more orange than a real dawn. It is lopsided in a way no atmosphere is, because somebody painted it to read as dawn at a glance, on a CRT, in a game where you might be looking at it for four seconds before turning around. Replace it with a correct atmosphere and you have thrown away the part somebody chose.

So the modern version keeps it, at a seam that does not cost anything:

  • Luminance from the physics. This is what carries the day/night cycle, what the exposure curve consumes, and what makes stars appear without anybody scheduling them.
  • Chroma from the palette, at the same angle-from-the-sun the dome would have used.

Slide the grade up on the figure above and the hues become the 2005 palette’s while the horizon band stays exactly where the physics put it. The result is as bright as the atmosphere says and as orange as the artist said, and — this is the part that matters — grading cannot move brightness, so none of it disturbs the exposure.

That is not a compromise between two techniques. It is how skies are actually graded in production: a physical base with an artist’s curve over it. EverQuest had only the curve. A renderer that has only the base has lost something.

Fog stops being a colour

The second thing the old sky cannot express is distance.

Its fog is lerp(surface, fog_colour, t), where fog_colour is one texel the server sends at zone-in. One colour, every direction, all day. The modern replacement is aerial perspective — integrate the air between the eye and the surface, and you get surface × transmittance + inscatter, where the in-scattered light arrived from the sun through that same air.

EverQuest — lerp toward one authored colour computed — transmittance and in-scatter sun 5° up · looking 0° from it (into the sun) resulting radiance, per channel 0 distance → dashed: lerp solid: integral
5°
0° from the sun
A row of identical grey surfaces receding from the eye, faded two ways. Enable WebAssembly to swing the view around the sun.

Swing the view around the sun and watch which strip moves. The curves underneath are the reason: EverQuest’s two channels both climb toward a common point, because that is all a lerp toward one colour can do. The computed ones diverge — red rising while blue falls — because looking into a low sun the air is adding red faster than it is passing blue.

A lerp cannot produce that shape at all. Not a badly tuned lerp; any lerp.

There is a lesson about scale hiding in this figure too. Air is clear: blue’s optical depth is about 0.03 per kilometre, so six kilometres of atmosphere passes more than four fifths of the light. To show aerial perspective at all the strip has to run to sixty kilometres. It is a mountain-range effect, which is why painters named it after landscapes.

What the rest of the list costs

Sun and moon. EverQuest drew both as white billboards with all the colour and the rays in the texture’s alpha. Modern: an analytic limb-darkened disc at its true angular diameter, about half a degree, with bloom doing the glow the alpha ramp faked. The moon becomes a textured sphere with its phase from the sun/moon/observer geometry, and an earthshine term on the dark limb.

Stars. Swap the procedural placement for a real catalogue, magnitudes mapped to luminance, rendered as points through a point-spread function or baked to a cubemap. Twinkle stops being a sixty-byte table and becomes scintillation modulated by airmass, so stars near the horizon shimmer harder than those overhead — which is true and which EverQuest’s table could not express, for the same reason its dome could not express a horizon band.

The day/night gate gets better by disappearing. Stars are always there physically; they are outshone. With the exposure doing its job you get EverQuest’s multiply-by-zero for free, and correctly, with no schedule.

Clouds. Their sprites are 54-vertex meshes with a per-vertex tint computed by a twice-truncating integer bilinear. That tint is doing by hand, at 54 points, what an aerial-perspective lookup now does per pixel. The modern version is either the same idea with real per-pixel lighting, or raymarched volumetrics if you can afford them.

Culling. This is the one part that does not survive. The dome-as-far-bound was a beautiful trick and it is obsolete: GPU-driven culling does the coarse work now, and distant terrain fades through aerial perspective rather than being cut by an opaque sphere. The sky goes back to being drawn last, which is where it was always supposed to be.

What is actually the same

It is tempting to read all of this as the old sky being replaced. It is worth noticing how much of it is the same shape.

A modern atmosphere is not evaluated per pixel. It is evaluated into a handful of small lookup tables — transmittance, multiple scattering, a sky view — once, when the sun moves, and then sampled. The tables are tens of texels on a side.

Which is to say: the 2025 sky is a small table, indexed by a couple of angles, sampled per pixel. So was the 2005 one. The difference is not the architecture. The difference is that one table is computed from a model of the air and the other was painted by hand — and, as the figures above show, that the painted one is missing a coordinate it could never have had.

The rest of it, EverQuest got right the first time.


Every number in the figures on this page is computed in your browser from the parameters in skycore::modern — the scattering coefficients, the phase functions, the ozone tent — and the EverQuest halves come from the same ColorMap data the previous post’s figures use. Neither half is a screenshot of anything.

The multiple-scattering term is the one approximation: a constant-albedo ambient rather than the second-order integral a production implementation evaluates into its own table. It is visible mainly in how bright the sky floor sits after sunset.