npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aeronautic/lights

v0.2.0

Published

Physically based aircraft lights for three.js and React Three Fiber: navigation lights over the arcs and intensities of CS/FAR 25, anti-collision strobes seen as the eye sees a flash (Blondel–Rey), landing and taxi beams as photometric cones scattering in

Readme

@aeronautic/lights

npm CI MIT

A delta fighter on the apron at night, its strobes flashing and its red beacon lit, the navigation lights handing over to the white tail light as the camera goes round, rendered with @aeronautic/lights

Physically based aircraft lights for React Three Fiber and three.js, written in TSL for three's WebGPURenderer.

  • Navigation lights: red to the left, green to the right, white astern, over the arcs and with the intensities of the airworthiness rules (CS/FAR 25.1385–1397). Seen from outside its arc, a light falls to the spill the rule allows.
  • Anti-collision lights: flashing 40 to 100 times a minute (25.1401). Each flash is seen at its Blondel–Rey effective intensity, not its peak.
  • Landing and taxi lights: their beams as photometric cones that light the ground, and show in the air through what it scatters.
  • Glare from the light's real luminance and the exposure: the eye's own scatter round a point of light (CIE 146), not a bloom tuned by eye.
  • The air: haze and molecules dim each light, the blue more than the red, with the day's visibility.

None of it is drawn to a size or a timer. How bright a light looks is its intensity towards the camera, over the distance squared, less what the air takes, at the scene's exposure.

Docs · Live example on the docs' fighter

The docs have guides, the live example, the full reference and how the lights are worked out. This README is the short version.

Install

pnpm add @aeronautic/lights @aeronautic/core three@~0.186

The same peer dependencies as the other packages: @aeronautic/core, three 0.186.x, plus react 19 and @react-three/fiber 9 (or 10) for @aeronautic/lights/react. It needs a WebGPURenderer, which falls back to WebGL 2 by itself. It doesn't run on the classic WebGLRenderer. In R3F, gl={webgpu_gl()} from @aeronautic/core/react makes one.

Quick start

<Lights> is a group where the aircraft's reference point sits. Put it inside the model, and say where the lights are:

import { useGLTF } from "@react-three/drei";
import { Lights } from "@aeronautic/lights/react";
import { useMemo } from "react";

export const Jet = () => {
  const { scene, nodes } = useGLTF("/jet.glb");

  // Nodes of the model, read every frame, or positions in metres. A lamp
  // points along its node's -Z
  const airframe = useMemo(
    () => ({
      navigation: [
        { side: "left", at: nodes.Nav_L },
        { side: "right", at: nodes.Nav_R },
        { side: "aft", at: nodes.Nav_Tail },
      ],
      anticollision: [
        { at: nodes.Strobe_Top, color: "white" },
        { at: nodes.Beacon_Bottom, color: "red", phaseS: 0.5 },
      ],
      beams: [{ at: nodes.Landing, lamp: "landing", onGear: true }],
    }),
    [nodes],
  );

  return (
    <group>
      <primitive object={scene} />
      <Lights airframe={airframe} air={{ visibilityM: 4000 }} />
    </group>
  );
};

onGear holds a lamp off until the gear is down: give gear, 0 up to 1 down, or let a <FlightProvider> from @aeronautic/core give it.

The lights are in candela and the scene's light in cd/m²: look.exposure is the number one cd/m² is drawn as. By default it is EV100 3, a floodlit apron at night; exposure_ev100 from @aeronautic/lights/physics gives it for another.

The dials

Each is a physical quantity in SI units:

  • airframe: where the navigation, anti-collision and beam lights are, and which lamp each beam is.
  • switches: navigation, anticollision, landing and taxi.
  • navigation: how many times the rule's minimum the lights give, how much spill past their arcs, and their colours.
  • anticollision: the effective intensity, the flash rate and the flash's shape.
  • air: altitudeM and visibilityM.
  • look: the exposure, the observer's age and eyes, and whether a flash is seen by an eye or a camera.
  • illuminate: which lights also light the scene, as three lights.

How it works

  • The rule. Each navigation light's intensity is the minimum CS/FAR 25 sets for the direction it is seen from, in the aircraft's axes, times scale. Past its arc it falls to the overlap the rule allows. The colours are inside the rule's chromaticity boxes.
  • Flashes. A flash's effective intensity is Blondel and Rey's ∫ I dt / (0.2 + t₂ − t₁), over the window that makes it largest. 400 cd effective from a xenon tube dying away in 0.2 ms takes a peak of about 403 000 cd.
  • The air. Molecules scatter as Rayleigh found, as λ⁻⁴, and a continental haze as λ^-1.3, Ångström's exponent. Koschmieder's 3.912 over the visibility gives the extinction at 550 nm, the haze's share being what the molecules leave.
  • Glare. CIE 146's glare spread function, for the observer's age and eyes, times the illuminance at the eye. It is drawn out to where it falls below what the screen shows.
  • Beams. A lamp's beam is a Gaussian falling to a tenth of the peak at half the catalogue's spread. It lights the scene as a spot light, and the air is summed along each ray through its cone, with Henyey–Greenstein scattering.

What it leaves out

  • The haze between a lamp and the ground it lights: under a per cent at a taxi light's distances.
  • A lens's flare: the glare is the eye's, with no spikes or ghosts.
  • The intensity towards the camera is worked out once a frame, from where the camera was when the frame began.
  • A page's own bloom, if it has one, adds to the glare.

License

MIT © Romain Le Gall