diff --git a/src/main.rs b/src/main.rs index fdb5253..24c1137 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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() => { diff --git a/src/render/gpustate.rs b/src/render/gpustate.rs index 0748b6a..de4296f 100644 --- a/src/render/gpustate.rs +++ b/src/render/gpustate.rs @@ -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 { - let instances: Vec = 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 { + 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);