Only generate starfield when necessary

master
Mark 2023-12-24 07:33:09 -08:00
parent 0b3f9fdd9e
commit 6ec95d17a9
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
2 changed files with 38 additions and 26 deletions

View File

@ -165,6 +165,8 @@ pub async fn run() -> Result<()> {
let mut gpu = GPUState::new(window).await?;
let mut game = Game::new();
gpu.on_new_system(&game);
event_loop.run(move |event, _, control_flow| {
match event {
Event::RedrawRequested(window_id) if window_id == gpu.window().id() => {

View File

@ -30,6 +30,7 @@ pub struct GPUState {
sprite_pipeline: wgpu::RenderPipeline,
starfield_pipeline: wgpu::RenderPipeline,
starfield_count: u32,
texture_array: TextureArray,
global_data: GlobalData,
@ -179,6 +180,7 @@ impl GPUState {
texture_array,
global_data,
vertex_buffers,
starfield_count: 0,
});
}
@ -252,17 +254,28 @@ impl GPUState {
/// Will panic if STARFIELD_INSTANCE_LIMIT is exceeded.
///
/// This is only called inside self.render()
fn make_starfield_instances(&self, game: &Game) -> Vec<StarfieldInstance> {
let instances: Vec<StarfieldInstance> = game
.system
.starfield
.iter()
.map(|s| StarfieldInstance {
position: s.pos.into(),
parallax: s.parallax,
height: s.height,
})
.collect();
fn make_starfield_instances(&mut self, game: &Game) -> Vec<StarfieldInstance> {
let mut instances = Vec::new();
let sz = STARFIELD_SIZE as f32;
for offset in [
Vector2 { x: 0.0, y: 0.0 },
Vector2 { x: 0.0, y: sz },
Vector2 { x: sz, y: sz },
Vector2 { x: sz, y: 0.0 },
Vector2 { x: sz, y: -sz },
Vector2 { x: 0.0, y: -sz },
Vector2 { x: -sz, y: -sz },
Vector2 { x: -sz, y: 0.0 },
Vector2 { x: -sz, y: sz },
] {
for s in &game.system.starfield {
instances.push(StarfieldInstance {
position: (s.pos + offset).into(),
parallax: s.parallax,
height: s.height,
})
}
}
// Enforce starfield limit
if instances.len() as u64 > Self::STARFIELD_INSTANCE_LIMIT {
@ -270,9 +283,20 @@ impl GPUState {
unreachable!("Starfield limit exceeded!")
}
self.starfield_count = instances.len() as u32;
return instances;
}
pub fn on_new_system(&mut self, game: &Game) {
// Create starfield instances
let starfield_instances = self.make_starfield_instances(game);
self.queue.write_buffer(
&self.vertex_buffers.starfield.instances,
0,
bytemuck::cast_slice(&starfield_instances),
);
}
pub fn render(&mut self, game: &Game) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_texture()?;
let view = output
@ -328,14 +352,6 @@ impl GPUState {
bytemuck::cast_slice(&sprite_instances),
);
// Create starfield instances
let starfield_instances = self.make_starfield_instances(game);
self.queue.write_buffer(
&self.vertex_buffers.starfield.instances,
0,
bytemuck::cast_slice(&starfield_instances),
);
// These should match the indices in each shader,
// and should each have a corresponding bind group layout.
render_pass.set_bind_group(0, &self.texture_array.bind_group, &[]);
@ -344,13 +360,7 @@ impl GPUState {
// Starfield pipeline
self.vertex_buffers.starfield.set_in_pass(&mut render_pass);
render_pass.set_pipeline(&self.starfield_pipeline);
render_pass.draw(0..1, 0..starfield_instances.len() as _);
render_pass.draw_indexed(
0..SPRITE_INDICES.len() as u32,
0,
0..starfield_instances.len() as _,
);
render_pass.draw_indexed(0..SPRITE_INDICES.len() as u32, 0, 0..self.starfield_count);
// Sprite pipeline
self.vertex_buffers.sprite.set_in_pass(&mut render_pass);