sunlight through atmosphere

This commit is contained in:
connor committed 2026-10-18 12:09:21 -04:00
1 parent 8c0a1439d7
commit 8e57375059
18 files changed
+1921 -134

No files matched your search

+3
View File
@@ -189,6 +189,9 @@ fn render(args: &RenderArgs) -> Result<(), String> {
let file = SceneFile::read(path)?;
let dir = path.parent().unwrap_or(Path::new("."));
let mut camera = file.camera(dir)?;
if let (LightingTier::L0, Some(exposure)) = (args.lighting, file.camera.exposure_l0) {
camera.exposure = exposure;
}
if args.noiseless {
camera.detector = camera.detector.noiseless();
}
+6 -1
View File
@@ -63,6 +63,10 @@ pub struct CameraFile {
pub principal_point: Option<[f64; 2]>,
pub f_number: Option<f64>,
pub exposure: Option<f64>,
/// The exposure at lighting L0 in place of `exposure`, for a scene whose bodies L0
/// draws far brighter than L1 does (a lunar eclipse, which L0 draws without Earth's
/// shadow).
pub exposure_l0: Option<f64>,
pub transmission: Option<f64>,
pub gain: Option<f64>,
pub bias: Option<f64>,
@@ -540,7 +544,7 @@ mod tests {
#[test]
fn camera_overrides_apply() {
let file: SceneFile = toml::from_str(&format!(
"{MINIMAL}\n[camera]\nwidth = 640\nexposure = 2e-3\nadc_bits = 10\nread_noise = 2.5\n\
"{MINIMAL}\n[camera]\nwidth = 640\nexposure = 2e-3\nexposure_l0 = 5e-4\nadc_bits = 10\nread_noise = 2.5\n\
dark_current = 0\nshot_noise = false\nprnu = 0.02\nhot_pixels = [1e-3, 20]\n\
pattern_seed = 9\nblooming = {{ column = 0.25 }}\n"
))
@@ -548,6 +552,7 @@ mod tests {
let camera = file.camera(Path::new(".")).unwrap();
assert_eq!((camera.width, camera.height), (640, 1080));
assert_eq!(camera.exposure, 2e-3);
assert_eq!(file.camera.exposure_l0, Some(5e-4));
assert_eq!(camera.detector.adc_bits, 10);
let d = camera.detector;
assert_eq!(
+15 -12
View File
@@ -185,21 +185,24 @@ fn pretty_previews_lift_the_darks_and_leave_space_black() {
#[cfg(feature = "astrokit")]
#[test]
fn lunar_eclipse_darkens_the_moon() {
// Mid-totality: at L1 the whole Moon is in Earth's umbra and reads the bias. At L0
// there are no eclipses on the bodies and it is a full Moon.
fn lunar_eclipse_darkens_and_reddens_the_moon() {
// Mid-totality: at L1 the whole Moon is in Earth's umbra, lit only through Earth's
// atmosphere, red, and brighter at its northern edge, farther from the shadow's
// axis, than at its southern. At L0 there are no eclipses on the bodies, and the
// full Moon at the scene's L0 exposure, 300 times shorter, is bright but short of
// saturation.
let scene = "examples/scenes/lunar-eclipse.toml";
let l0 = render_at(scene, "gpu", "L0");
let l1 = render_at(scene, "gpu", "L1");
assert!(
l0.get_pixel(960, 540).0.iter().all(|&v| v > 150),
"{:?}",
l0.get_pixel(960, 540)
);
assert!(
l1.pixels().all(|p| p.0 == [64; 3]),
"every pixel at the bias"
);
let full = l0.get_pixel(960, 540).0;
assert!(full.iter().all(|&v| v > 1000 && v < 4000), "{full:?}");
let [north, center, south] = [260, 540, 820].map(|y| l1.get_pixel(960, y).0);
// Measured: 695, 287, 145 DN at the north, 592, 164, 77 at the center, 208, 82, 65
// at the south, over a bias of 64.
for p in [north, center, south] {
assert!(p[0] > p[1] && p[1] >= p[2] && p[2] >= 64, "{p:?}");
}
assert!(north[0] > center[0] && center[0] > south[0] && south[0] > 100);
}
#[cfg(feature = "astrokit")]