Fixed starfield tiling

master
Mark 2023-12-24 12:01:38 -08:00
parent babd410182
commit 6f01e7d3bd
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
1 changed files with 16 additions and 10 deletions

View File

@ -48,7 +48,7 @@ impl GPUState {
pub const SPRITE_INSTANCE_LIMIT: u64 = 100; pub const SPRITE_INSTANCE_LIMIT: u64 = 100;
// Must be small enough to fit in an i32 // Must be small enough to fit in an i32
pub const STARFIELD_INSTANCE_LIMIT: u64 = STARFIELD_COUNT * 9; pub const STARFIELD_INSTANCE_LIMIT: u64 = STARFIELD_COUNT * 24;
pub async fn new(window: Window) -> Result<Self> { pub async fn new(window: Window) -> Result<Self> {
let window_size = window.inner_size(); let window_size = window.inner_size();
@ -264,18 +264,19 @@ impl GPUState {
// Compute window size in starfield tiles // Compute window size in starfield tiles
let mut nw_tile: Point2<i32> = { let mut nw_tile: Point2<i32> = {
// Game coordinates (relative to camera) of nw corner of screen. // Game coordinates (relative to camera) of nw corner of screen.
let clip_nw = Point2::from((self.window_aspect, 1.0)) * ZOOM_MAX / 2.0; let clip_nw = Point2::from((self.window_aspect, 1.0)) * ZOOM_MAX;
// Adjust for parallax // Parallax correction.
// Also, adjust v for mod to work properly
// (v is centered at 0)
let v: Point2<f32> = clip_nw * STARFIELD_PARALLAX_MIN; let v: Point2<f32> = clip_nw * STARFIELD_PARALLAX_MIN;
let v_adj: Point2<f32> = (v.x + (sz / 2.0), v.y + (sz / 2.0)).into();
// We don't need to adjust coordinates here, since clip_nw is always positive.
#[rustfmt::skip] #[rustfmt::skip]
// Compute m = fmod(x, sz) // Compute m = fmod(x, sz)
let m: Vector2<f32> = ( let m: Vector2<f32> = (
(v.x - (v.x / sz).floor() * sz), (v_adj.x - (v_adj.x / sz).floor() * sz) - (sz / 2.0),
(v.y - (v.y / sz).floor() * sz) (v_adj.y - (v_adj.y / sz).floor() * sz) - (sz / 2.0)
).into(); ).into();
// Now, remainder and convert to "relative tile" coordinates // Now, remainder and convert to "relative tile" coordinates
@ -286,9 +287,15 @@ impl GPUState {
(rel.x.round() as i32, rel.y.round() as i32).into() (rel.x.round() as i32, rel.y.round() as i32).into()
}; };
// We need to cover the window with stars,
// but we also need a one-wide buffer to account for motion.
nw_tile += Vector2::from((1, 1));
// Truncate tile grid to buffer size // Truncate tile grid to buffer size
// (The window won't be full of stars if we don't have a large enough instance limit) // (The window won't be full of stars if our instance limit is too small)
while (nw_tile.x * 2 + 1) * (nw_tile.y * 2 + 1) > Self::STARFIELD_INSTANCE_LIMIT as i32 { while ((nw_tile.x * 2 + 1) * (nw_tile.y * 2 + 1) * STARFIELD_COUNT as i32)
> Self::STARFIELD_INSTANCE_LIMIT as i32
{
nw_tile -= Vector2::from((1, 1)); nw_tile -= Vector2::from((1, 1));
} }
@ -313,7 +320,6 @@ impl GPUState {
// Enforce starfield limit // Enforce starfield limit
if instances.len() as u64 > Self::STARFIELD_INSTANCE_LIMIT { if instances.len() as u64 > Self::STARFIELD_INSTANCE_LIMIT {
// TODO: no panic, handle this better.
unreachable!("Starfield limit exceeded!") unreachable!("Starfield limit exceeded!")
} }