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 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<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 {
input: InputStatus,
last_update: Instant,

View File

@ -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<StarfieldInstance> {
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<StarfieldInstance> = 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(),
}]),
);

View File

@ -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<f32>(global.window_aspect, 1.0)
);
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;
return out;
}

View File

@ -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(),
};
}

View File

@ -10,6 +10,7 @@ pub struct StarfieldStar {
// These are relative to the center of a starfield tile.
pub pos: Point2<Pfloat>,
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,
});