Fixed parallax

master
Mark 2023-12-23 23:56:10 -08:00
parent 4abbcca1d4
commit 1661b5c3af
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
5 changed files with 27 additions and 41 deletions

View File

@ -1,5 +1,5 @@
use anyhow::Result; use anyhow::Result;
use cgmath::{Deg, EuclideanSpace, Point2}; use cgmath::{Deg, Point2};
use winit::{ use winit::{
event::{ event::{
ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase, ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase,
@ -65,20 +65,6 @@ struct Sprite {
parallax: Pfloat, parallax: Pfloat,
} }
impl Sprite {
const PARALLAX_STRENGTH: Pfloat = 0.1;
pub fn post_parallax(parallax: Pfloat, pos: Point2<Pfloat>, camera: Camera) -> Point2<Pfloat> {
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<Pfloat> {
return Self::post_parallax(self.parallax, self.pos, camera);
}
}
struct Game { struct Game {
input: InputStatus, input: InputStatus,
last_update: Instant, last_update: Instant,

View File

@ -211,7 +211,8 @@ impl GPUState {
let clip_sw = Point2::from((1.0, -1.0)) * game.camera.zoom; let clip_sw = Point2::from((1.0, -1.0)) * game.camera.zoom;
for s in game.sprites() { 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[..]); let texture = self.texture_array.get_texture(&s.name[..]);
// Game dimensions of this sprite post-scale. // Game dimensions of this sprite post-scale.
@ -263,17 +264,16 @@ impl GPUState {
/// ///
/// This is only called inside self.render() /// This is only called inside self.render()
fn make_starfield_instances(&self, game: &Game) -> Vec<StarfieldInstance> { fn make_starfield_instances(&self, game: &Game) -> Vec<StarfieldInstance> {
let mut instances = Vec::new(); let instances: Vec<StarfieldInstance> = game
for s in &game.system.starfield { .system
// TODO: minimize operations here .starfield
//let pos = Sprite::post_parallax(s.parallax, s.pos * 500.0, game.camera) .iter()
// - game.camera.pos.to_vec(); .map(|s| StarfieldInstance {
instances.push(StarfieldInstance {
position: s.pos.into(), position: s.pos.into(),
parallax: s.parallax, parallax: s.parallax,
height: 2.0, height: s.height,
}); })
} .collect();
// Enforce starfield limit // Enforce starfield limit
if instances.len() as u64 > Self::STARFIELD_INSTANCE_LIMIT { if instances.len() as u64 > Self::STARFIELD_INSTANCE_LIMIT {
@ -326,7 +326,7 @@ impl GPUState {
camera_zoom: game.camera.zoom, camera_zoom: game.camera.zoom,
window_aspect: self.window_aspect, window_aspect: self.window_aspect,
starfield_texture: 1, starfield_texture: 1,
starfield_tile_size: 1000.0, starfield_tile_size: 80000.0,
padding: Default::default(), padding: Default::default(),
}]), }]),
); );

View File

@ -42,9 +42,9 @@ fn vertex_shader_main(
global.camera_position global.camera_position
- ( - (
fmod( 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
) - 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 // (Note that instance position is in a different
// coordinate system than usual) // coordinate system than usual)
let camera_pos = (instance.position + tile_center) - global.camera_position; let camera_pos = (instance.position + tile_center) - global.camera_position;
let parallax_vector = -camera_pos * instance.parallax * 0.1;
// Translate // Translate
pos = pos + ( pos = pos + (
// Don't forget to correct distance for screen aspect ratio too! // Don't forget to correct distance for screen aspect ratio too!
// The minus in "minus parallax_vector" is important. (camera_pos / (global.camera_zoom * instance.parallax))
((camera_pos + parallax_vector) / global.camera_zoom)
/ vec2<f32>(global.window_aspect, 1.0) / vec2<f32>(global.window_aspect, 1.0)
); );
var out: VertexOutput; var out: VertexOutput;
out.position = vec4<f32>(pos, 0.0, 1.0); out.position = vec4<f32>(pos, 0.0, 1.0) * instance.parallax;
out.texture_coords = vertex.texture_coords; out.texture_coords = vertex.texture_coords;
return out; return out;
} }

View File

@ -41,7 +41,7 @@ impl Spriteable for Ship {
name: self.kind.sprite().to_owned(), name: self.kind.sprite().to_owned(),
angle: self.body.angle, angle: self.body.angle,
scale: 1.0, scale: 1.0,
parallax: 0.0, parallax: 1.0,
height: self.kind.height(), height: self.kind.height(),
}; };
} }

View File

@ -10,6 +10,7 @@ pub struct StarfieldStar {
// These are relative to the center of a starfield tile. // These are relative to the center of a starfield tile.
pub pos: Point2<Pfloat>, pub pos: Point2<Pfloat>,
pub parallax: Pfloat, pub parallax: Pfloat,
pub height: Pfloat,
} }
pub struct System { pub struct System {
@ -22,13 +23,14 @@ impl System {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let mut s = System { let mut s = System {
bodies: Vec::new(), bodies: Vec::new(),
starfield: (0..500) starfield: (0..1000)
.map(|_| StarfieldStar { .map(|_| StarfieldStar {
pos: Point2 { pos: Point2 {
x: rng.gen_range(-500.0..500.0), x: rng.gen_range(-40000.0..40000.0),
y: rng.gen_range(-500.0..500.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(), .collect(),
}; };
@ -36,19 +38,19 @@ impl System {
s.bodies.push(Doodad { s.bodies.push(Doodad {
pos: (0.0, 0.0).into(), pos: (0.0, 0.0).into(),
sprite: "a0".to_owned(), sprite: "a0".to_owned(),
parallax: 3.0, parallax: 4.0,
height: 80.0, height: 80.0,
}); });
s.bodies.push(Doodad { s.bodies.push(Doodad {
pos: Polar { pos: Polar {
center: (0.0, 0.0).into(), center: (0.0, 0.0).into(),
radius: 100.0, radius: 200.0,
angle: Deg { 0: 31.0 }, angle: Deg { 0: 31.0 },
} }
.to_cartesian(), .to_cartesian(),
sprite: "earth".to_owned(), sprite: "earth".to_owned(),
parallax: 1.0, parallax: 2.0,
height: 120.0, height: 120.0,
}); });
@ -60,7 +62,7 @@ impl System {
} }
.to_cartesian(), .to_cartesian(),
sprite: "small".to_owned(), sprite: "small".to_owned(),
parallax: -1.0, parallax: 0.5,
height: 50.0, height: 50.0,
}); });