diff --git a/src/main.rs b/src/main.rs index 2368d1a..8b67cae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use cgmath::{Deg, EuclideanSpace, Point2}; +use cgmath::{Deg, Point2}; use winit::{ event::{ ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase, @@ -65,20 +65,6 @@ struct Sprite { parallax: Pfloat, } -impl Sprite { - const PARALLAX_STRENGTH: Pfloat = 0.1; - - pub fn post_parallax(parallax: Pfloat, pos: Point2, camera: Camera) -> Point2 { - let v = camera.pos.to_vec() - pos.to_vec(); - return pos + (v * parallax * Self::PARALLAX_STRENGTH); - } - - /// Returns post-parallax position in game coordinates. - pub fn post_parallax_position(&self, camera: Camera) -> Point2 { - return Self::post_parallax(self.parallax, self.pos, camera); - } -} - struct Game { input: InputStatus, last_update: Instant, diff --git a/src/render/gpustate.rs b/src/render/gpustate.rs index 9c706e3..ff6e2e1 100644 --- a/src/render/gpustate.rs +++ b/src/render/gpustate.rs @@ -211,7 +211,8 @@ impl GPUState { let clip_sw = Point2::from((1.0, -1.0)) * game.camera.zoom; for s in game.sprites() { - let pos = s.post_parallax_position(game.camera) - game.camera.pos.to_vec(); + // Parallax is computed here, so we can check if this sprite is visible. + let pos = (s.pos - game.camera.pos.to_vec()) / s.parallax; let texture = self.texture_array.get_texture(&s.name[..]); // Game dimensions of this sprite post-scale. @@ -263,17 +264,16 @@ impl GPUState { /// /// This is only called inside self.render() fn make_starfield_instances(&self, game: &Game) -> Vec { - let mut instances = Vec::new(); - for s in &game.system.starfield { - // TODO: minimize operations here - //let pos = Sprite::post_parallax(s.parallax, s.pos * 500.0, game.camera) - // - game.camera.pos.to_vec(); - instances.push(StarfieldInstance { + let instances: Vec = game + .system + .starfield + .iter() + .map(|s| StarfieldInstance { position: s.pos.into(), parallax: s.parallax, - height: 2.0, - }); - } + height: s.height, + }) + .collect(); // Enforce starfield limit if instances.len() as u64 > Self::STARFIELD_INSTANCE_LIMIT { @@ -326,7 +326,7 @@ impl GPUState { camera_zoom: game.camera.zoom, window_aspect: self.window_aspect, starfield_texture: 1, - starfield_tile_size: 1000.0, + starfield_tile_size: 80000.0, padding: Default::default(), }]), ); diff --git a/src/render/shaders/starfield.wgsl b/src/render/shaders/starfield.wgsl index f97171a..62dbf97 100644 --- a/src/render/shaders/starfield.wgsl +++ b/src/render/shaders/starfield.wgsl @@ -42,9 +42,9 @@ fn vertex_shader_main( global.camera_position - ( fmod( - global.camera_position + global.starfield_tile_size/2.0, + global.camera_position + global.starfield_tile_size / 2.0, global.starfield_tile_size - ) - global.starfield_tile_size/2.0 + ) - global.starfield_tile_size / 2.0 ) ); @@ -60,18 +60,16 @@ fn vertex_shader_main( // (Note that instance position is in a different // coordinate system than usual) let camera_pos = (instance.position + tile_center) - global.camera_position; - let parallax_vector = -camera_pos * instance.parallax * 0.1; // Translate pos = pos + ( // Don't forget to correct distance for screen aspect ratio too! - // The minus in "minus parallax_vector" is important. - ((camera_pos + parallax_vector) / global.camera_zoom) + (camera_pos / (global.camera_zoom * instance.parallax)) / vec2(global.window_aspect, 1.0) ); var out: VertexOutput; - out.position = vec4(pos, 0.0, 1.0); + out.position = vec4(pos, 0.0, 1.0) * instance.parallax; out.texture_coords = vertex.texture_coords; return out; } diff --git a/src/ship.rs b/src/ship.rs index 01ba18a..65f7efc 100644 --- a/src/ship.rs +++ b/src/ship.rs @@ -41,7 +41,7 @@ impl Spriteable for Ship { name: self.kind.sprite().to_owned(), angle: self.body.angle, scale: 1.0, - parallax: 0.0, + parallax: 1.0, height: self.kind.height(), }; } diff --git a/src/system.rs b/src/system.rs index c20c584..17a0db1 100644 --- a/src/system.rs +++ b/src/system.rs @@ -10,6 +10,7 @@ pub struct StarfieldStar { // These are relative to the center of a starfield tile. pub pos: Point2, pub parallax: Pfloat, + pub height: Pfloat, } pub struct System { @@ -22,13 +23,14 @@ impl System { let mut rng = rand::thread_rng(); let mut s = System { bodies: Vec::new(), - starfield: (0..500) + starfield: (0..1000) .map(|_| StarfieldStar { pos: Point2 { - x: rng.gen_range(-500.0..500.0), - y: rng.gen_range(-500.0..500.0), + x: rng.gen_range(-40000.0..40000.0), + y: rng.gen_range(-40000.0..40000.0), }, - parallax: rng.gen_range(10.0..11.0), + parallax: rng.gen_range(100.0..150.0), + height: rng.gen_range(1.0..2.0), }) .collect(), }; @@ -36,19 +38,19 @@ impl System { s.bodies.push(Doodad { pos: (0.0, 0.0).into(), sprite: "a0".to_owned(), - parallax: 3.0, + parallax: 4.0, height: 80.0, }); s.bodies.push(Doodad { pos: Polar { center: (0.0, 0.0).into(), - radius: 100.0, + radius: 200.0, angle: Deg { 0: 31.0 }, } .to_cartesian(), sprite: "earth".to_owned(), - parallax: 1.0, + parallax: 2.0, height: 120.0, }); @@ -60,7 +62,7 @@ impl System { } .to_cartesian(), sprite: "small".to_owned(), - parallax: -1.0, + parallax: 0.5, height: 50.0, });