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 gpu = GPUState::new(window).await?;
let mut game = Game::new(); let mut game = Game::new();
gpu.on_new_system(&game);
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, _, control_flow| {
match event { match event {
Event::RedrawRequested(window_id) if window_id == gpu.window().id() => { Event::RedrawRequested(window_id) if window_id == gpu.window().id() => {

View File

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