Limb darkening for the sun

This commit is contained in:
connor committed 2026-10-14 22:23:04 -04:00
1 parent 85896b17a4
commit 377bdc92df
21 files changed
+1019 -103

No files matched your search

+103 -16
View File
@@ -413,9 +413,10 @@ disk, which is the feature horizon-based navigation measures.
- **The Moon** is a sphere of 1737.4 km radius. From Earth's distance it
is about 0.52 degrees across, 82 pixels in the example camera.
- **The Sun** is a sphere of 695,700 km radius: 0.53 degrees across, about
85 pixels in the example camera. Its disk has the solar radiance from the
folding section above, and it is drawn only where no nearer body covers
it. So Earth eclipses it naturally.
85 pixels in the example camera. Averaged over its disk it has the solar
radiance from the folding section above; from lighting L1 its center is
brighter than its edge (see "The Sun's disk" below). It is drawn only
where no nearer body covers it, so Earth eclipses it naturally.
### Shading
@@ -519,6 +520,84 @@ calibrated reflectance product itself, so its values are close but not exact
reflectances. A calibrated alternative (MODIS's albedo product) is a possible
later refinement.
### The Sun's disk
Code: `sun.rs`, `shaders/common.wgsl`, `shaders/bodies.wgsl`. From lighting
L1.
The Sun's disk is brighter at its center than at its edge: limb darkening.
Light leaving the Sun comes from a layer a few hundred kilometers deep in
which the gas gets hotter with depth. Looking at the center of the disk, the
line of sight goes straight down into hot gas; near the edge it runs through
the layer at a slant and sees higher, cooler gas, which shines less.
Where the line of sight meets the Sun's surface, call mu the cosine of the
angle between it and the surface's normal: 1 at the center of the disk, 0 at
the edge, 0.5 at 87 % of the way out. Neckel and Labs (1994) measured the
brightness across the disk at 30 wavelengths from 303 to 1099 nm, and
Hestroffer and Magnan (1998) showed that at each wavelength it is close to
mu^alpha times the center's, to about 1 %. Alpha is 0.94 at 303 nm, 0.48 at
580 nm and 0.26 at 1099 nm: blue light darkens much more toward the edge
than red. The renderer uses their values of alpha, interpolated between those
wavelengths and held constant outside them.
The total light from the disk does not change; that is the measured solar
spectrum. Only its spread does. A disk of brightness mu^alpha averages 2 /
(alpha + 2) of its center, so the center is (alpha + 2) / 2 times the mean.
Folded through the example camera's channels, the center is 1.22, 1.26 and
1.31 times the mean in red, green and blue, and 87 % of the way to the edge
(mu = 0.5) the disk is 0.70 of its center's brightness in green. The
folding is exact: for each channel the renderer weights every wavelength's
profile by that channel's solar flux and tabulates the result, so any channel
layout works.
It matters in two places:
- **The Sun in an image.** A camera that looks at the Sun almost always
saturates, but not with a dark filter, a Sun sensor, or once the lens's
blur spreads the Sun's light into the pixels around it (M3).
- **Eclipses.** When Earth or the Moon covers part of the Sun, what counts is
how much light it hides, not how much of the disk's area. Near the umbra
only a sliver of the dim edge is left, so less light gets through than the
area says: 7000 km behind Earth, 25 km inside the penumbra's dark side,
4.5 % in green against 6.1 %. Near the outside of the penumbra the covered
part is dim edge, so more gets through: 88.2 % against 86.0 %. In an
annular solar eclipse the Moon covers the bright center and leaves the dim
ring: 1 % of the light reaches the ground, not the 2.4 % of the disk's area.
The renderer computes the light hidden by an occulter in two parts. Circles
around the Sun's center that the occulter covers completely count through a
table of the light inside each radius. Circles it covers in part count by
adding up, over eight radii, each circle's brightness times the length of its
arc inside the occulter, with the radii placed by a Gauss-Legendre rule; eight radii are within 2.4e-5
of what 32 give. The same
calculation runs on the CPU for each target's eclipse and on the GPU for
every pixel of Earth and the Moon in an eclipse, per channel.
Tests: every pixel of the Sun seen through a 250 mm lens (420 pixels across)
reads its mean radiance times the profile at its mu, to 6e-5, and the disk's
light summed over pixels is the channel's solar flux to 7e-5. The light
hidden by an occulter matches a fine sum over the disk to within 1e-4, and a
uniform disk gives the area overlap. In eclipses the tests of the sections below use
the limb-darkened light.
Cost: nothing measurable on the RTX 3060 unless an eclipse is in view. With
Earth filling the image and most of it in the Moon's penumbra, the bodies
pass takes 0.43 ms instead of 0.21 ms; lavapipe 9.5 ms instead of 5.0 ms.
Limitations:
- **The very edge.** Hestroffer and Magnan fitted the profiles over the
inner 90 % of the radius, where measurements are reliable. Right at the
edge mu^alpha falls to zero, faster than the measured Sun does, over the
outermost fraction of a percent of the radius.
- **Wavelengths outside 303 to 1099 nm** use the end values. The example
camera's channels are inside that range.
- **A quiet Sun.** Sunspots and bright faculae change the Sun's output by
about 0.1 % over the solar cycle and are not modeled.
- **Shadows on the target** (above) still treat the Sun as a square of
uniform brightness in their penumbra.
### Depth from the bodies
The pass also writes each hit's depth, near / z, as described in the
@@ -653,7 +732,8 @@ Limitations:
- **Penumbra shape.** The grid averages a square of the map, so brightness
rises in a straight line across the penumbra. A real disk-shaped Sun
rises along an S-shaped curve: the full width is the same, but the middle
80 % of the change is 0.69 of the width rather than 0.8.
80 % of the change is 0.69 of the width rather than 0.8. Limb darkening
(from L1) would steepen it a little more, and is not modeled here either.
- **Resolution.** A detail smaller than a texel casts no reliable shadow. A
gap narrower than about 2 texels between a blocker and the surface it
shades (a few mm on Landsat 8) lets light through, because of the acne
@@ -686,6 +766,11 @@ satellites (Montenbruck and Gill), the same as astrokit's. A test checks it
against tracing lines from the target to thousands of points spread over
the solar disk.
From lighting L1 the fraction is of the Sun's light rather than its area,
per channel, because the disk is brighter at its center (see "The Sun's
disk"); that makes a penumbra darker toward the umbra and brighter toward
the outside than the area alone says.
The renderer counts both Earth and the Moon as occulters. The fraction is
computed once per target, at its center. The whole target
dims together, which is accurate unless the target is a sizable fraction of
@@ -700,9 +785,10 @@ lighting L1.
Earth and the Moon also shadow each other. When the Moon passes through
Earth's shadow it is a lunar eclipse; when the Moon's shadow falls on Earth,
a solar eclipse. For every pixel that sees Earth or the Moon, the shader
works out the fraction of the Sun's disk visible from that point on the
surface, past the other body, with the same overlap of circles as for the
target, and multiplies the point's sunlight by it.
works out the fraction of the Sun's light that reaches that point on the
surface past the other body, with the same overlap of circles and the same
limb-darkened disk as for the target, and multiplies the point's sunlight by
it, per channel.
The sizes involved:
@@ -713,7 +799,8 @@ The sizes involved:
closest, the umbra touches down as a dark spot up to about 270 km across:
a total solar eclipse. When it is farther, the umbra ends in space, and
beyond its tip the Moon covers only the middle of the Sun's disk, leaving a
ring: an annular eclipse, where a few percent of the Sun still shows. The
ring: an annular eclipse, where about 1 % of the Sun's light still arrives,
the dim edge of the disk. The
penumbra around either is about 7000 km across.
The overlap is computed in 32-bit floats, which is enough: a lunar surface
@@ -731,8 +818,9 @@ Tests (`tests/eclipses.rs`), on the GPU and lavapipe, compare each pixel of
Earth and the Moon against the 64-bit model at that pixel's surface point:
the Moon entirely in Earth's umbra, the Moon across the umbra's edge, a
total solar eclipse and an annular one. Pixels the model puts fully in shadow
read exactly zero, those it puts fully outside are unchanged, and the rest
agree to within 1e-4 of the Sun's light (9e-7 at most on the GPU, 5e-5 on
read zero, those it puts fully outside are unchanged (both to within 1e-6,
the 32-bit rounding at the shadow's edges), and the rest
agree to within 1e-4 of the Sun's light (1.2e-6 at most on the GPU, 5e-5 on
lavapipe). The command-line tests render two real eclipses from their
epochs: the total lunar eclipse of 2025 March 14 at mid-totality, where the
whole Moon reads the bias, and the total solar eclipse of 2026 August 12,
@@ -745,9 +833,11 @@ direction of the Sun, which is 26 degrees high there; NASA gives the path as
The light Earth and the Moon reflect onto targets (next section) includes
these shadows, so an eclipsed Moon sheds less light.
On the RTX 3060 this adds nothing measurable to the bodies pass (0.202 to
0.205 ms with Earth filling the image). On lavapipe it adds about 1 ms when
Earth or the Moon fills much of the image.
On the RTX 3060 this adds nothing measurable to the bodies pass unless an
eclipse is in view; with Earth filling the image and most of it in the
Moon's penumbra, the pass takes 0.43 ms instead of 0.20 ms, most of it the
limb-darkened sum (see "The Sun's disk"). On lavapipe, 9.5 ms instead of
3.9 ms.
Limitations:
@@ -758,8 +848,6 @@ Limitations:
radius, as for the target's eclipses; its flattening would move the
shadow's edge on the Moon by about 20 km. The Moon's mountains and valleys,
which shape the edge of a solar eclipse's path, are not modeled.
- **Uniform Sun.** The Sun's disk is taken as uniformly bright until limb
darkening (M2) arrives.
### Light from Earth and the Moon
@@ -882,7 +970,6 @@ velocity as an input, which the scene does not carry yet.
| Effect | Where |
|---|---|
| Earthshine on the Moon's night side | M4 |
| The Sun as a disk that is darker toward its edge (limb darkening) | M2 |
| Pixel-area sampling (anti-aliasing): graded edges, thin parts | M3 |
| Lens distortion | M3 |
| Blur from diffraction and lens imperfections (point spread function) | M3 |