aeronautic

Dials and radiance

Why params, profile and quality are separate, and where the radiance is set.

Three kinds of dial, and why they are separate

Where it livesWhat changing it costsWhat is in it
AfterburnerParamsone instancea buffer write, on a version bumpthe engine, in SI units: nozzle radius, exit Mach, pressure ratio, exit and dry temperatures, gamma, molar mass, soot and its survival, particles and their albedo, afterburning, band emission, turbulence, meander, refraction
AfterburnerProfilebatch uniformsan uploadthe world and the camera: altitude, the day's temperature offset, airspeed, exposure, sky light, the visibility cut, the longest plume, the burner threshold, the shock train's shaping, the eddies, the shutter, the step safety
AfterburnerQualityuniforms, and one compile-time octave countan upload; a recompile for octavesmarch iterations near and mid, noise octaves

There is no length among the params and only one colour. A plume's length comes out of its nozzle and its gas, through the potential-core and mixing-layer correlations. Its colour comes out of its temperature, through Planck's law. The one exception is bandColor, the light of the radicals burning in the gas, which is a line spectrum and not a temperature.

The split is not tidiness. Params ride on the instance because two engines on one airframe may burn differently and a formation may not. The attribute budget is real: against a WebGPU floor of sixteen attributes and eight buffers, the tier index rides in v_origin.w rather than taking a varying slot of its own. The profile is uniforms because every plume shares it, and a slider on it must not recompile a shader mid-drag. That includes the air: atmosphere(profile) walks the standard atmosphere once on the main thread, and the shader is handed temperature, pressure, density, the speed of sound and the ram as five more uniforms. The step counts are uniforms too: WGSL loops may run to a uniform bound, and the march breaks early anyway. Octaves stay compiled in, because an octave the compiler cannot see is an octave it cannot fold away.


Why the radiance is bounded, and where to set it

The march is not an open sum. It solves the radiative transfer along the ray: what the gas emits at each step, attenuated by what lies in front of it (Beer-Lambert), and a transmittance for what lies behind. Without that, a ray running the length of the plume adds twenty times what a ray crossing it adds. A plume is normally seen from behind the aircraft that is leaving, so that would be most rays.

The emission is physical. The gas glows as a blackbody at the local temperature, normalised so that one at 2000 K has a luminance of one (REFERENCE_TEMPERATURE_K). Soot emits and absorbs as one over the wavelength, which reddens it, and the band emission climbs as exp(-activationK / T). A real plume therefore runs from a thousandth of the reference to a thousand times it, and exposure is the single number that decides which part of that the tone curve sees. It is a camera's exposure, not a brightness dial. Set it for the hottest thing you want to keep shape in. Past that point the core and the disks clip, which is what they do in a photograph too.

The blend is premultiplied, One, OneMinusSrcAlpha. A clean plume emits and covers almost nothing, a sooty one covers what is behind it, and neither an additive blend nor straight alpha does both. Three's own premultipliedAlpha flag stays off: the radiance is premultiplied already, and the flag would multiply it by the coverage a second time, so a hydrogen plume (all emission, no coverage) would vanish.

If the plume ever looks like an airbrushed cone, check exposure first and turbulence second.

On this page