Added stars at L1

This commit is contained in:
connor committed 2026-10-16 14:43:50 -04:00
1 parent e0381ccdd7
commit 970551b4e1
26 files changed
+2118 -55

No files matched your search

+32 -9
View File
@@ -11,7 +11,7 @@ use clap::{Args, Parser, Subcommand};
use resolved::gpu::AdapterChoice;
use resolved::{
CameraTier, EarthTexture, Fidelity, Frame, LightingTier, Look, MoonTexture, Preview, Renderer,
RendererOptions,
RendererOptions, StarCatalog, StarPhotometry,
};
use crate::scene_file::SceneFile;
@@ -52,13 +52,15 @@ struct RenderArgs {
#[arg(long)]
pretty: bool,
/// Lighting fidelity tier: L0, or L1 (adds Earth's surface, shadows on targets,
/// light from Earth and the Moon, eclipses on them, and the Sun's limb darkening;
/// needs Blue Marble data).
/// light from Earth and the Moon, eclipses on them, the Sun's limb darkening, and
/// stars, which camera C1 shows; needs Blue Marble data, and with C1 the star
/// catalog).
#[arg(long, default_value = "L0")]
lighting: LightingTier,
/// Camera fidelity tier: C0, or C1 (adds pixels that collect light over their area,
/// for graded edges and continuous thin parts, lens distortion, lens blur, and the
/// Sun, Moon and Earth where light time and aberration make them appear).
/// Sun, Moon and Earth where light time and aberration make them appear, and at
/// lighting L1 stars).
#[arg(long, default_value = "C0")]
camera: CameraTier,
/// From camera C1: render each pixel as N x N finer ones (1 to 4; default 2), which
@@ -72,7 +74,8 @@ struct RenderArgs {
#[arg(long, value_name = "FRAMES")]
timings: Option<usize>,
/// Directory of data the tiers need (earth/bmng-2004-MM.jpg from
/// scripts/fetch-earth.sh, moon/wac-hapke-643.png from scripts/fetch-moon.py).
/// scripts/fetch-earth.sh, moon/wac-hapke-643.png from scripts/fetch-moon.py,
/// stars/stars.bin from scripts/fetch-stars.py).
/// Without it: RESOLVED_DATA, then ./data, then the repository's data/.
#[arg(long, value_name = "DIR")]
data: Option<PathBuf>,
@@ -124,12 +127,13 @@ fn earth_image(data: Option<&Path>, month: u32) -> Result<PathBuf, String> {
data,
&format!("earth/bmng-2004-{month:02}.jpg"),
"fetch-earth.sh",
"lighting L1",
)
}
/// `name` from the first data directory that has it; the error names `script`, which
/// makes it.
fn data_file(data: Option<&Path>, name: &str, script: &str) -> Result<PathBuf, String> {
/// makes it, and `tier`, which needs it.
fn data_file(data: Option<&Path>, name: &str, script: &str, tier: &str) -> Result<PathBuf, String> {
let tried = data_directories(data);
tried
.iter()
@@ -138,7 +142,7 @@ fn data_file(data: Option<&Path>, name: &str, script: &str) -> Result<PathBuf, S
.ok_or_else(|| {
let tried: Vec<_> = tried.iter().map(|d| d.display().to_string()).collect();
format!(
"lighting L1 needs {name} (run scripts/{script}, or pass --data DIR); looked in {}",
"{tier} needs {name} (run scripts/{script}, or pass --data DIR); looked in {}",
tried.join(", ")
)
})
@@ -171,6 +175,7 @@ fn render(args: &RenderArgs) -> Result<(), String> {
args.data.as_deref(),
"moon/wac-hapke-643.png",
"fetch-moon.py",
"lighting L1",
)?;
Some(Arc::new(
MoonTexture::load(&image).map_err(|e| e.to_string())?,
@@ -178,6 +183,22 @@ fn render(args: &RenderArgs) -> Result<(), String> {
} else {
None
};
let stars = if args.lighting >= LightingTier::L1 && args.camera >= CameraTier::C1 {
let catalog = data_file(
args.data.as_deref(),
"stars/stars.bin",
"fetch-stars.py",
"lighting L1 with camera C1",
)?;
// Only the stars this exposure can show.
let faint = StarPhotometry::new(&camera).faintest_drawn(camera.exposure);
Some(Arc::new(
StarCatalog::load(&catalog, file.years_since_j2000()?, faint)
.map_err(|e| e.to_string())?,
))
} else {
None
};
let texturing = start.elapsed();
let options = RendererOptions {
@@ -199,6 +220,7 @@ fn render(args: &RenderArgs) -> Result<(), String> {
shadow_map_size: None,
dn_in_place: None,
supersampling: args.supersampling,
stars,
};
let start = Instant::now();
let mut renderer = Renderer::new(camera, options).map_err(|e| e.to_string())?;
@@ -260,12 +282,13 @@ fn render(args: &RenderArgs) -> Result<(), String> {
v[v.len() / 2]
};
println!(
"gpu shadow {:.3} ms, earthshine {:.3} ms, mesh {:.3} ms, bodies {:.3} ms, blur {:.3} ms, sensor {:.3} ms, first to last {:.3} ms (medians)",
"gpu shadow {:.3} ms, earthshine {:.3} ms, mesh {:.3} ms, bodies {:.3} ms, blur {:.3} ms, stars {:.3} ms, sensor {:.3} ms, first to last {:.3} ms (medians)",
median(|t| t.shadow),
median(|t| t.earthshine),
median(|t| t.mesh),
median(|t| t.bodies),
median(|t| t.blur),
median(|t| t.stars),
median(|t| t.sensor),
median(|t| t.total)
);
+18
View File
@@ -223,6 +223,24 @@ impl SceneFile {
Ok(None)
}
/// Julian years from J2000.0 to the scene's epoch, for the stars' proper motion; 0
/// for a scene without one.
#[cfg(feature = "astrokit")]
pub fn years_since_j2000(&self) -> Result<f64> {
let Some(epoch) = &self.epoch else {
return Ok(0.0);
};
let epoch: hifitime::Epoch = epoch.parse().map_err(|e| format!("epoch {epoch:?}: {e}"))?;
let j2000 =
hifitime::Epoch::from_gregorian_hms(2000, 1, 1, 12, 0, 0, hifitime::TimeScale::TT);
Ok((epoch - j2000).to_unit(hifitime::Unit::Day) / 365.25)
}
#[cfg(not(feature = "astrokit"))]
pub fn years_since_j2000(&self) -> Result<f64> {
Ok(0.0)
}
/// The observer's pose.
pub fn observer(&self) -> Result<Pose> {
let o = &self.observer;