diff --git a/crates/render/src/gpustate/mod.rs b/crates/render/src/gpustate/mod.rs index deecf5d..89f6e7d 100644 --- a/crates/render/src/gpustate/mod.rs +++ b/crates/render/src/gpustate/mod.rs @@ -20,7 +20,6 @@ pub struct GPUState { object_pipeline: wgpu::RenderPipeline, starfield_pipeline: wgpu::RenderPipeline, - //particle_pipeline: wgpu::RenderPipeline, ui_pipeline: wgpu::RenderPipeline, radialbar_pipeline: wgpu::RenderPipeline, diff --git a/crates/render/src/gpustate/new.rs b/crates/render/src/gpustate/new.rs index 8c068b2..d8469f7 100644 --- a/crates/render/src/gpustate/new.rs +++ b/crates/render/src/gpustate/new.rs @@ -168,23 +168,6 @@ impl GPUState { .set_bind_group_layouts(bind_group_layouts) .build(); - /* - let particle_pipeline = PipelineBuilder::new("particle", &device) - .set_shader(&preprocess_shader( - &include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/shaders/", - "particle.wgsl" - )), - &global_uniform, - 1, - )) - .set_format(config.format) - .set_triangle(true) - .set_vertex_buffer(vertex_buffers.get_particle()) - .set_bind_group_layouts(bind_group_layouts) - .build();*/ - let radialbar_pipeline = PipelineBuilder::new("radialbar", &device) .set_shader(&preprocess_shader( &include_str!(concat!( @@ -230,7 +213,6 @@ impl GPUState { object_pipeline, starfield_pipeline, ui_pipeline, - //particle_pipeline, radialbar_pipeline, state, diff --git a/crates/render/src/gpustate/phys.rs b/crates/render/src/gpustate/phys.rs index fdc320b..c9c3db6 100644 --- a/crates/render/src/gpustate/phys.rs +++ b/crates/render/src/gpustate/phys.rs @@ -10,37 +10,35 @@ use crate::{ }; impl GPUState { - pub(super) fn phys_push_ship( + pub(super) fn phys_push_ships( &mut self, input: &RenderInput, // NE and SW corners of screen screen_clip: (Point2, Point2), ) { - for ship in input.systemsim.iter_ships() { - // TODO: move collapse sequence here? - + for s in input.phys_img.iter_ships() { let ship_pos; let ship_ang; let ship_cnt; - match ship.get_data().get_state() { + match s.ship.get_data().get_state() { ShipState::Dead | ShipState::Landed { .. } => continue, ShipState::Collapsing { .. } | ShipState::Flying { .. } => { - let r = input.systemsim.get_rigid_body(ship.rigid_body).unwrap(); + let r = &s.rigidbody; let pos = *r.translation(); ship_pos = Point3::new(pos.x, pos.y, 1.0); let ship_rot = r.rotation(); ship_ang = ship_rot.angle(); - ship_cnt = input.ct.get_ship(ship.get_data().get_content()); + ship_cnt = input.ct.get_ship(s.ship.get_data().get_content()); } ShipState::UnLanding { current_z, .. } | ShipState::Landing { current_z, .. } => { - let r = input.systemsim.get_rigid_body(ship.rigid_body).unwrap(); + let r = &s.rigidbody; let pos = *r.translation(); ship_pos = Point3::new(pos.x, pos.y, *current_z); let ship_rot = r.rotation(); ship_ang = ship_rot.angle(); - ship_cnt = input.ct.get_ship(ship.get_data().get_content()); + ship_cnt = input.ct.get_ship(s.ship.get_data().get_content()); } } @@ -85,7 +83,7 @@ impl GPUState { ); // Push this object's instance - let anim_state = ship.get_anim_state(); + let anim_state = s.ship.get_anim_state(); self.state.push_object_buffer(ObjectInstance { texture_index: anim_state.texture_index(), texture_fade: anim_state.fade, @@ -93,7 +91,7 @@ impl GPUState { }); if { - let is_flying = match ship.get_data().get_state() { + let is_flying = match s.ship.get_data().get_state() { ShipState::Flying { .. } | ShipState::UnLanding { .. } | ShipState::Landing { .. } => true, @@ -101,7 +99,7 @@ impl GPUState { }; is_flying } { - for (engine_point, anim) in ship.iter_engine_anim() { + for (engine_point, anim) in s.ship.iter_engine_anim() { self.state.queue.write_buffer( &self.state.global_uniform.object_buffer, ObjectData::SIZE * self.state.get_object_counter() as u64, @@ -135,18 +133,18 @@ impl GPUState { } } - pub(super) fn phys_push_projectile( + pub(super) fn phys_push_projectiles( &mut self, input: &RenderInput, // NE and SW corners of screen screen_clip: (Point2, Point2), ) { - for p in input.systemsim.iter_projectiles() { - let r = input.systemsim.get_rigid_body(p.rigid_body).unwrap(); + for p in input.phys_img.iter_projectiles() { + let r = &p.rigidbody; let proj_pos = *r.translation(); let proj_rot = r.rotation(); let proj_ang = proj_rot.angle(); - let proj_cnt = &p.content; // TODO: don't clone this? + let proj_cnt = &p.projectile.content; // TODO: don't clone this? // Position adjusted for parallax // TODO: adjust parallax for zoom? @@ -179,14 +177,14 @@ impl GPUState { ypos: proj_pos.y, zpos: 1.0, angle: proj_ang, - size: 0f32.max(proj_cnt.size + p.size_rng), + size: 0f32.max(proj_cnt.size + p.projectile.size_rng), parent: 0, is_child: 0, _padding: Default::default(), }]), ); - let anim_state = p.get_anim_state(); + let anim_state = p.projectile.get_anim_state(); self.state.push_object_buffer(ObjectInstance { texture_index: anim_state.texture_index(), texture_fade: anim_state.fade, @@ -251,4 +249,68 @@ impl GPUState { }); } } + + pub(super) fn phys_push_effects( + &mut self, + input: &RenderInput, + // NE and SW corners of screen + screen_clip: (Point2, Point2), + ) { + for p in input.phys_img.iter_effects() { + let r = &p.rigidbody; + let pos = *r.translation(); + let rot = r.rotation(); + let ang = rot.angle(); + + // Position adjusted for parallax + // TODO: adjust parallax for zoom? + // 1.0 is z-coordinate, which is constant for projectiles + let adjusted_pos = (pos - input.camera_pos) / 1.0; + + // Game dimensions of this sprite post-scale. + // Post-scale width or height, whichever is larger. + // This is in game units. + // + // We take the maximum to account for rotated sprites. + let m = (p.effect.size / 1.0) + * input + .ct + .get_sprite(p.effect.anim.get_sprite()) + .aspect + .max(1.0); + + // Don't draw sprites that are off the screen + if adjusted_pos.x < screen_clip.0.x - m + || adjusted_pos.y > screen_clip.0.y + m + || adjusted_pos.x > screen_clip.1.x + m + || adjusted_pos.y < screen_clip.1.y - m + { + continue; + } + + let idx = self.state.get_object_counter(); + // Write this object's location data + self.state.queue.write_buffer( + &self.state.global_uniform.object_buffer, + ObjectData::SIZE * idx as u64, + bytemuck::cast_slice(&[ObjectData { + xpos: pos.x, + ypos: pos.y, + zpos: 1.0, + angle: ang, + size: p.effect.size, + parent: 0, + is_child: 0, + _padding: Default::default(), + }]), + ); + + let anim_state = p.effect.anim.get_texture_idx(); + self.state.push_object_buffer(ObjectInstance { + texture_index: anim_state.texture_index(), + texture_fade: anim_state.fade, + object_index: idx as u32, + }); + } + } } diff --git a/crates/render/src/gpustate/render.rs b/crates/render/src/gpustate/render.rs index 60fe046..c3b601c 100644 --- a/crates/render/src/gpustate/render.rs +++ b/crates/render/src/gpustate/render.rs @@ -1,17 +1,12 @@ use anyhow::Result; use bytemuck; use galactica_system::{data::ShipState, phys::PhysSimShipHandle}; -use galactica_util::constants::PARTICLE_SPRITE_INSTANCE_LIMIT; use glyphon::Resolution; use nalgebra::Point2; use std::iter; use wgpu; -use crate::{ - globaluniform::GlobalDataContent, - vertexbuffer::{consts::SPRITE_INDICES, types::ParticleInstance}, - RenderInput, -}; +use crate::{globaluniform::GlobalDataContent, vertexbuffer::consts::SPRITE_INDICES, RenderInput}; impl<'a> super::GPUState { /// Render routines while player is flying @@ -46,25 +41,6 @@ impl<'a> super::GPUState { timestamp_writes: None, }); - // Write all new particles to GPU buffer - for i in input.particles.iter() { - let sprite = input.ct.get_sprite(i.sprite); - let texture_a = sprite.get_first_frame(); // ANIMATE - - self.state.push_particle_buffer(ParticleInstance { - position: [i.pos.x, i.pos.y], - velocity: i.velocity.into(), - angle: i.angle, - angvel: i.angvel, - size: i.size, - texture_index: [texture_a, texture_a], - texture_fade: 1.0, - created: input.current_time, - expires: input.current_time + i.lifetime, - fade: i.fade, - }); - } - // Create sprite instances // Game coordinates (relative to camera) of ne and sw corners of screen. @@ -76,8 +52,9 @@ impl<'a> super::GPUState { // The order inside ships and projectiles doesn't matter, // but ships should always be under projectiles. self.phys_push_system(&input, (clip_ne, clip_sw)); - self.phys_push_ship(&input, (clip_ne, clip_sw)); - self.phys_push_projectile(&input, (clip_ne, clip_sw)); + self.phys_push_ships(&input, (clip_ne, clip_sw)); + self.phys_push_projectiles(&input, (clip_ne, clip_sw)); + self.phys_push_effects(&input, (clip_ne, clip_sw)); self.ui.draw(&input, &mut self.state); // These should match the indices in each shader, @@ -109,19 +86,6 @@ impl<'a> super::GPUState { 0..self.state.get_object_counter(), ); - /* - // Particle pipeline - self.state - .vertex_buffers - .get_particle() - .set_in_pass(&mut render_pass); - render_pass.set_pipeline(&self.particle_pipeline); - render_pass.draw_indexed( - 0..SPRITE_INDICES.len() as u32, - 0, - 0..PARTICLE_SPRITE_INSTANCE_LIMIT as _, - ); */ - // Ui pipeline self.state .vertex_buffers @@ -319,9 +283,10 @@ impl<'a> super::GPUState { self.state.frame_reset(); match input - .systemsim + .phys_img .get_ship(&PhysSimShipHandle(input.player.ship.unwrap())) .unwrap() + .ship .get_data() .get_state() { diff --git a/crates/render/src/vertexbuffer/types.rs b/crates/render/src/vertexbuffer/types.rs index 6399522..5703311 100644 --- a/crates/render/src/vertexbuffer/types.rs +++ b/crates/render/src/vertexbuffer/types.rs @@ -224,112 +224,6 @@ impl BufferObject for UiInstance { } } -#[repr(C)] -#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] -pub struct ParticleInstance { - /// World position of this particle - pub position: [f32; 2], - - /// Velocity of this particle, in world coordinates - pub velocity: [f32; 2], - - /// Angle of this particle, in radians - pub angle: f32, - - /// Angular velocity of this particle, rad/sec - pub angvel: f32, - - /// The height of this particle, in world units - pub size: f32, - - /// The time, in seconds, at which this particle was created. - /// Time is kept by a variable in the global uniform. - pub created: f32, - - /// The time, in seconds, at which this particle expires. - /// Time is kept by a variable in the global uniform. - pub expires: f32, - - /// Fade this particle out over this many seconds as it expires - pub fade: f32, - - /// What texture to use for this particle - pub texture_index: [u32; 2], - /// Fade parameter for texture index - pub texture_fade: f32, -} - -impl BufferObject for ParticleInstance { - fn layout() -> wgpu::VertexBufferLayout<'static> { - wgpu::VertexBufferLayout { - array_stride: Self::SIZE, - step_mode: wgpu::VertexStepMode::Instance, - attributes: &[ - // Position - wgpu::VertexAttribute { - offset: 0, - shader_location: 2, - format: wgpu::VertexFormat::Float32x2, - }, - // Velocity - wgpu::VertexAttribute { - offset: mem::size_of::<[f32; 2]>() as wgpu::BufferAddress, - shader_location: 3, - format: wgpu::VertexFormat::Float32x2, - }, - // Angle - wgpu::VertexAttribute { - offset: mem::size_of::<[f32; 4]>() as wgpu::BufferAddress, - shader_location: 4, - format: wgpu::VertexFormat::Float32, - }, - // Angvel - wgpu::VertexAttribute { - offset: mem::size_of::<[f32; 5]>() as wgpu::BufferAddress, - shader_location: 5, - format: wgpu::VertexFormat::Float32, - }, - // Size - wgpu::VertexAttribute { - offset: mem::size_of::<[f32; 6]>() as wgpu::BufferAddress, - shader_location: 6, - format: wgpu::VertexFormat::Float32, - }, - // Created - wgpu::VertexAttribute { - offset: mem::size_of::<[f32; 7]>() as wgpu::BufferAddress, - shader_location: 7, - format: wgpu::VertexFormat::Float32, - }, - // Expires - wgpu::VertexAttribute { - offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress, - shader_location: 8, - format: wgpu::VertexFormat::Float32, - }, - // Fade - wgpu::VertexAttribute { - offset: mem::size_of::<[f32; 9]>() as wgpu::BufferAddress, - shader_location: 9, - format: wgpu::VertexFormat::Float32, - }, - // Texture - wgpu::VertexAttribute { - offset: mem::size_of::<[f32; 10]>() as wgpu::BufferAddress, - shader_location: 10, - format: wgpu::VertexFormat::Uint32x2, - }, - // Texture fade - wgpu::VertexAttribute { - offset: mem::size_of::<[f32; 12]>() as wgpu::BufferAddress, - shader_location: 11, - format: wgpu::VertexFormat::Float32, - }, - ], - } - } -} - #[repr(C)] #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] pub struct RadialBarInstance {