Minor cleanup

master
Mark 2024-01-08 19:11:46 -08:00
parent 744533c05c
commit 861c1ce8e6
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
4 changed files with 282 additions and 157 deletions

View File

@ -51,6 +51,10 @@ pub const OBJECT_SPRITE_INSTANCE_LIMIT: u64 = 500;
/// We can draw at most this many ui sprites on the screen. /// We can draw at most this many ui sprites on the screen.
pub const UI_SPRITE_INSTANCE_LIMIT: u64 = 100; pub const UI_SPRITE_INSTANCE_LIMIT: u64 = 100;
/// We can draw at most this many radual bars on the screen.
/// This is fairly small, since we know exactly how many of these we'll draw (for now)
pub const RADIALBAR_SPRITE_INSTANCE_LIMIT: u64 = 10;
/// The size of our circular particle buffer. When we create particles, the oldest ones are replaced. /// The size of our circular particle buffer. When we create particles, the oldest ones are replaced.
pub const PARTICLE_SPRITE_INSTANCE_LIMIT: u64 = 1000; pub const PARTICLE_SPRITE_INSTANCE_LIMIT: u64 = 1000;

View File

@ -12,7 +12,7 @@ use crate::{
}; };
impl GPUState { impl GPUState {
pub(super) fn hud_add_radar(&mut self, state: &RenderState, instances: &mut Vec<UiInstance>) { pub(super) fn hud_add_radar(&mut self, state: &RenderState) {
let radar_range = 4000.0; let radar_range = 4000.0;
let radar_size = 300.0; let radar_size = 300.0;
let hide_range = 0.85; let hide_range = 0.85;
@ -26,14 +26,26 @@ impl GPUState {
let ship_sprite = state.content.get_sprite_handle("ui::shipblip"); let ship_sprite = state.content.get_sprite_handle("ui::shipblip");
let arrow_sprite = state.content.get_sprite_handle("ui::centerarrow"); let arrow_sprite = state.content.get_sprite_handle("ui::centerarrow");
instances.push(UiInstance { // Enforce buffer limit
anchor: PositionAnchor::NwNw.to_int(), if self.vertex_buffers.ui_counter as u64 > galactica_constants::UI_SPRITE_INSTANCE_LIMIT {
position: [10.0, -10.0], // TODO: no panic, handle this better.
angle: 0.0, panic!("UI limit exceeded!")
size: radar_size, }
color: [1.0, 1.0, 1.0, 1.0],
sprite_index: state.content.get_sprite_handle("ui::radar").get_index(), // Push this object's instance
}); self.queue.write_buffer(
&self.vertex_buffers.ui.instances,
UiInstance::SIZE * self.vertex_buffers.ui_counter,
bytemuck::cast_slice(&[UiInstance {
anchor: PositionAnchor::NwNw.to_int(),
position: [10.0, -10.0],
angle: 0.0,
size: radar_size,
color: [1.0, 1.0, 1.0, 1.0],
sprite_index: state.content.get_sprite_handle("ui::radar").get_index(),
}]),
);
self.vertex_buffers.ui_counter += 1;
/* /*
// Draw system objects // Draw system objects
@ -95,14 +107,28 @@ impl GPUState {
y: radar_size / -2.0 - 10.0, y: radar_size / -2.0 - 10.0,
} + (d * (radar_size / 2.0)); } + (d * (radar_size / 2.0));
instances.push(UiInstance { // Enforce buffer limit
anchor: PositionAnchor::NwC.to_int(), if self.vertex_buffers.ui_counter as u64
position: position.into(), > galactica_constants::UI_SPRITE_INSTANCE_LIMIT
angle: -Rad::from(angle).0, // TODO: consistent angles {
size, // TODO: no panic, handle this better.
color: f.into(), panic!("UI limit exceeded!")
sprite_index: ship_sprite.get_index(), }
});
// Push this object's instance
self.queue.write_buffer(
&self.vertex_buffers.ui.instances,
UiInstance::SIZE * self.vertex_buffers.ui_counter,
bytemuck::cast_slice(&[UiInstance {
anchor: PositionAnchor::NwC.to_int(),
position: position.into(),
angle: -Rad::from(angle).0, // TODO: consistent angles
size,
color: f.into(),
sprite_index: ship_sprite.get_index(),
}]),
);
self.vertex_buffers.ui_counter += 1;
} }
} }
@ -118,57 +144,85 @@ impl GPUState {
let sprite = state.content.get_sprite_handle("ui::radarframe"); let sprite = state.content.get_sprite_handle("ui::radarframe");
let size = 7.0f32.min((0.8 - m) * 70.0); let size = 7.0f32.min((0.8 - m) * 70.0);
instances.push(UiInstance { // Enforce buffer limit (this section adds four items)
anchor: PositionAnchor::NwNw.to_int(), if self.vertex_buffers.ui_counter as u64 + 4
position: Point2 { > galactica_constants::UI_SPRITE_INSTANCE_LIMIT
x: (radar_size / 2.0 + 10.0) - d.x, {
y: (radar_size / -2.0 - 10.0) + d.y, // TODO: no panic, handle this better.
} panic!("UI limit exceeded!")
.into(), }
angle: 0.0,
size,
color,
sprite_index: sprite.get_index(),
});
instances.push(UiInstance { self.queue.write_buffer(
anchor: PositionAnchor::NwSw.to_int(), &self.vertex_buffers.ui.instances,
position: Point2 { UiInstance::SIZE * self.vertex_buffers.ui_counter,
x: (radar_size / 2.0 + 10.0) - d.x, bytemuck::cast_slice(&[UiInstance {
y: (radar_size / -2.0 - 10.0) - d.y, anchor: PositionAnchor::NwNw.to_int(),
} position: Point2 {
.into(), x: (radar_size / 2.0 + 10.0) - d.x,
angle: Rad::from(Deg(90.0)).0, y: (radar_size / -2.0 - 10.0) + d.y,
size, }
color, .into(),
sprite_index: sprite.get_index(), angle: 0.0,
}); size,
color,
sprite_index: sprite.get_index(),
}]),
);
self.vertex_buffers.ui_counter += 1;
instances.push(UiInstance { self.queue.write_buffer(
anchor: PositionAnchor::NwSe.to_int(), &self.vertex_buffers.ui.instances,
position: Point2 { UiInstance::SIZE * self.vertex_buffers.ui_counter,
x: (radar_size / 2.0 + 10.0) + d.x, bytemuck::cast_slice(&[UiInstance {
y: (radar_size / -2.0 - 10.0) - d.y, anchor: PositionAnchor::NwSw.to_int(),
} position: Point2 {
.into(), x: (radar_size / 2.0 + 10.0) - d.x,
angle: Rad::from(Deg(180.0)).0, y: (radar_size / -2.0 - 10.0) - d.y,
size, }
color, .into(),
sprite_index: sprite.get_index(), angle: Rad::from(Deg(90.0)).0,
}); size,
color,
sprite_index: sprite.get_index(),
}]),
);
self.vertex_buffers.ui_counter += 1;
instances.push(UiInstance { self.queue.write_buffer(
anchor: PositionAnchor::NwNe.to_int(), &self.vertex_buffers.ui.instances,
position: Point2 { UiInstance::SIZE * self.vertex_buffers.ui_counter,
x: (radar_size / 2.0 + 10.0) + d.x, bytemuck::cast_slice(&[UiInstance {
y: (radar_size / -2.0 - 10.0) + d.y, anchor: PositionAnchor::NwSe.to_int(),
} position: Point2 {
.into(), x: (radar_size / 2.0 + 10.0) + d.x,
angle: Rad::from(Deg(270.0)).0, y: (radar_size / -2.0 - 10.0) - d.y,
size, }
color, .into(),
sprite_index: sprite.get_index(), angle: Rad::from(Deg(180.0)).0,
}); size,
color,
sprite_index: sprite.get_index(),
}]),
);
self.vertex_buffers.ui_counter += 1;
self.queue.write_buffer(
&self.vertex_buffers.ui.instances,
UiInstance::SIZE * self.vertex_buffers.ui_counter,
bytemuck::cast_slice(&[UiInstance {
anchor: PositionAnchor::NwNe.to_int(),
position: Point2 {
x: (radar_size / 2.0 + 10.0) + d.x,
y: (radar_size / -2.0 - 10.0) + d.y,
}
.into(),
angle: Rad::from(Deg(270.0)).0,
size,
color,
sprite_index: sprite.get_index(),
}]),
);
self.vertex_buffers.ui_counter += 1;
} }
// Arrow to center of system // Arrow to center of system
@ -182,31 +236,60 @@ impl GPUState {
y: radar_size / -2.0 - 10.0, y: radar_size / -2.0 - 10.0,
} + ((q.normalize() * 0.865) * (radar_size / 2.0)); } + ((q.normalize() * 0.865) * (radar_size / 2.0));
instances.push(UiInstance { if self.vertex_buffers.ui_counter as u64 > galactica_constants::UI_SPRITE_INSTANCE_LIMIT
anchor: PositionAnchor::NwC.to_int(), {
position: position.into(), // TODO: no panic, handle this better.
angle: -player_angle.0, panic!("UI limit exceeded!")
size: 10.0, }
color: [1.0, 1.0, 1.0, 1f32.min((m - 200.0) / 400.0)],
sprite_index: arrow_sprite.get_index(), self.queue.write_buffer(
}); &self.vertex_buffers.ui.instances,
UiInstance::SIZE * self.vertex_buffers.ui_counter,
bytemuck::cast_slice(&[UiInstance {
anchor: PositionAnchor::NwC.to_int(),
position: position.into(),
angle: -player_angle.0,
size: 10.0,
color: [1.0, 1.0, 1.0, 1f32.min((m - 200.0) / 400.0)],
sprite_index: arrow_sprite.get_index(),
}]),
);
self.vertex_buffers.ui_counter += 1;
} }
} }
pub(super) fn hud_add_status(&mut self, state: &RenderState, instances: &mut Vec<UiInstance>) { pub(super) fn hud_add_status(&mut self, state: &RenderState) {
instances.push(UiInstance { if self.vertex_buffers.ui_counter as u64 > galactica_constants::UI_SPRITE_INSTANCE_LIMIT {
anchor: PositionAnchor::NeNe.to_int(), // TODO: no panic, handle this better.
position: [-10.0, -10.0], panic!("UI limit exceeded!")
angle: 0.0, }
size: 200.0,
color: [1.0, 1.0, 1.0, 1.0], self.queue.write_buffer(
sprite_index: state.content.get_sprite_handle("ui::status").get_index(), &self.vertex_buffers.ui.instances,
}); UiInstance::SIZE * self.vertex_buffers.ui_counter,
bytemuck::cast_slice(&[UiInstance {
anchor: PositionAnchor::NeNe.to_int(),
position: [-10.0, -10.0],
angle: 0.0,
size: 200.0,
color: [1.0, 1.0, 1.0, 1.0],
sprite_index: state.content.get_sprite_handle("ui::status").get_index(),
}]),
);
self.vertex_buffers.ui_counter += 1;
// We add two items here, so +2
if self.vertex_buffers.radialbar_counter as u64 + 2
> galactica_constants::RADIALBAR_SPRITE_INSTANCE_LIMIT
{
// TODO: no panic, handle this better.
panic!("Radialbar limit exceeded!")
}
// TODO: counters for each buffer, remove arrays // TODO: counters for each buffer, remove arrays
self.queue.write_buffer( self.queue.write_buffer(
&self.vertex_buffers.radialbar.instances, &self.vertex_buffers.radialbar.instances,
RadialBarInstance::SIZE * 0, RadialBarInstance::SIZE * self.vertex_buffers.radialbar_counter,
bytemuck::cast_slice(&[RadialBarInstance { bytemuck::cast_slice(&[RadialBarInstance {
position: [-19.0, -19.0], position: [-19.0, -19.0],
anchor: PositionAnchor::NeNe.to_int(), anchor: PositionAnchor::NeNe.to_int(),
@ -216,10 +299,11 @@ impl GPUState {
angle: -state.current_time / 2.0, angle: -state.current_time / 2.0,
}]), }]),
); );
self.vertex_buffers.radialbar_counter += 1;
self.queue.write_buffer( self.queue.write_buffer(
&self.vertex_buffers.radialbar.instances, &self.vertex_buffers.radialbar.instances,
RadialBarInstance::SIZE * 1, RadialBarInstance::SIZE * self.vertex_buffers.radialbar_counter,
bytemuck::cast_slice(&[RadialBarInstance { bytemuck::cast_slice(&[RadialBarInstance {
position: [-27.0, -27.0], position: [-27.0, -27.0],
anchor: PositionAnchor::NeNe.to_int(), anchor: PositionAnchor::NeNe.to_int(),
@ -229,5 +313,6 @@ impl GPUState {
angle: state.current_time / 5.0, angle: state.current_time / 5.0,
}]), }]),
); );
self.vertex_buffers.radialbar_counter += 1;
} }
} }

View File

@ -5,7 +5,7 @@ use galactica_constants;
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
use std::{iter, rc::Rc}; use std::{iter, rc::Rc};
use wgpu; use wgpu::{self, BufferAddress};
use winit::{self, window::Window}; use winit::{self, window::Window};
use crate::{ use crate::{
@ -58,16 +58,17 @@ pub struct GPUState {
} }
struct VertexBuffers { struct VertexBuffers {
// Keeps track of length of each buffer
pub object_counter: BufferAddress,
pub ui_counter: BufferAddress,
pub particle_counter: BufferAddress,
pub radialbar_counter: BufferAddress,
object: Rc<VertexBuffer>, object: Rc<VertexBuffer>,
starfield: Rc<VertexBuffer>, starfield: Rc<VertexBuffer>,
ui: Rc<VertexBuffer>, ui: Rc<VertexBuffer>,
/// The index of the next particle slot we'll write to.
/// This must cycle to 0 whenever it exceeds the size
/// of the particle instance array.
particle_array_head: u64,
particle: Rc<VertexBuffer>, particle: Rc<VertexBuffer>,
radialbar: Rc<VertexBuffer>, radialbar: Rc<VertexBuffer>,
} }
@ -171,6 +172,11 @@ impl GPUState {
} }
let vertex_buffers = VertexBuffers { let vertex_buffers = VertexBuffers {
object_counter: 0,
ui_counter: 0,
particle_counter: 0,
radialbar_counter: 0,
object: Rc::new(VertexBuffer::new::<TexturedVertex, ObjectInstance>( object: Rc::new(VertexBuffer::new::<TexturedVertex, ObjectInstance>(
"object", "object",
&device, &device,
@ -195,7 +201,6 @@ impl GPUState {
galactica_constants::UI_SPRITE_INSTANCE_LIMIT, galactica_constants::UI_SPRITE_INSTANCE_LIMIT,
)), )),
particle_array_head: 0,
particle: Rc::new(VertexBuffer::new::<TexturedVertex, ParticleInstance>( particle: Rc::new(VertexBuffer::new::<TexturedVertex, ParticleInstance>(
"particle", "particle",
&device, &device,
@ -345,55 +350,30 @@ impl GPUState {
self.update_starfield_buffer() self.update_starfield_buffer()
} }
/// Make an instance for all the game's sprites /// Entrypoint for all vertex buffer builders
/// (Objects and UI) pub(super) fn update_all_buffers(&mut self, state: &RenderState) {
/// This will Will panic if any X_SPRITE_INSTANCE_LIMIT is exceeded.
fn update_sprite_instances(&mut self, state: &RenderState) -> (usize, usize) {
let mut object_instances: Vec<ObjectInstance> = Vec::new();
// Game coordinates (relative to camera) of ne and sw corners of screen. // Game coordinates (relative to camera) of ne and sw corners of screen.
// Used to skip off-screen sprites. // Used to skip off-screen sprites.
let clip_ne = Point2::from((-self.window_aspect, 1.0)) * state.camera_zoom; let clip_ne = Point2::from((-self.window_aspect, 1.0)) * state.camera_zoom;
let clip_sw = Point2::from((self.window_aspect, -1.0)) * state.camera_zoom; let clip_sw = Point2::from((self.window_aspect, -1.0)) * state.camera_zoom;
// TODO:sort. Order matters. // TODO: sorting. We don't need to sort ships, but we do need to sort system objects by z-level
// (which we don't yet draw)
// that should probably be done in iter_system().
// Order matters, it determines what is drawn on top.
// The order inside ships and projectiles doesn't matter,
// but ships should always be under projectiles.
for s in state.world.iter_ships() { for s in state.world.iter_ships() {
self.world_push_ship(state, (clip_ne, clip_sw), &s, &mut object_instances); self.world_push_ship(state, (clip_ne, clip_sw), &s);
} }
for p in state.world.iter_projectiles() { for p in state.world.iter_projectiles() {
self.world_push_projectile(state, (clip_ne, clip_sw), &p, &mut object_instances); self.world_push_projectile(state, (clip_ne, clip_sw), &p);
} }
// Enforce sprite limit self.hud_add_radar(state);
if object_instances.len() as u64 > galactica_constants::OBJECT_SPRITE_INSTANCE_LIMIT { self.hud_add_status(state);
// TODO: no panic, handle this better.
panic!("Sprite limit exceeded!")
}
self.queue.write_buffer(
&self.vertex_buffers.object.instances,
0,
bytemuck::cast_slice(&object_instances),
);
// TODO: we don't need an array, just use a counter
let mut ui_instances: Vec<UiInstance> = Vec::new();
self.hud_add_radar(state, &mut ui_instances);
self.hud_add_status(state, &mut ui_instances);
if ui_instances.len() as u64 > galactica_constants::UI_SPRITE_INSTANCE_LIMIT {
panic!("Ui sprite limit exceeded!")
}
self.queue.write_buffer(
&self.vertex_buffers.ui.instances,
0,
bytemuck::cast_slice(&ui_instances),
);
return (object_instances.len(), ui_instances.len());
} }
/// Make a StarfieldInstance for each star that needs to be drawn. /// Make a StarfieldInstance for each star that needs to be drawn.
@ -457,6 +437,11 @@ impl GPUState {
timestamp_writes: None, timestamp_writes: None,
}); });
self.vertex_buffers.object_counter = 0;
self.vertex_buffers.ui_counter = 0;
self.vertex_buffers.radialbar_counter = 0;
// Don't reset particle counter, it's special
let s = state.content.get_starfield_handle(); let s = state.content.get_starfield_handle();
// Update global values // Update global values
@ -488,7 +473,7 @@ impl GPUState {
for i in state.particles.iter() { for i in state.particles.iter() {
self.queue.write_buffer( self.queue.write_buffer(
&self.vertex_buffers.particle.instances, &self.vertex_buffers.particle.instances,
ParticleInstance::SIZE * self.vertex_buffers.particle_array_head, ParticleInstance::SIZE * self.vertex_buffers.particle_counter,
bytemuck::cast_slice(&[ParticleInstance { bytemuck::cast_slice(&[ParticleInstance {
position: [i.pos.x, i.pos.y], position: [i.pos.x, i.pos.y],
velocity: i.velocity.into(), velocity: i.velocity.into(),
@ -501,17 +486,17 @@ impl GPUState {
fade: i.fade, fade: i.fade,
}]), }]),
); );
self.vertex_buffers.particle_array_head += 1; self.vertex_buffers.particle_counter += 1;
if self.vertex_buffers.particle_array_head if self.vertex_buffers.particle_counter
== galactica_constants::PARTICLE_SPRITE_INSTANCE_LIMIT == galactica_constants::PARTICLE_SPRITE_INSTANCE_LIMIT
{ {
self.vertex_buffers.particle_array_head = 0; self.vertex_buffers.particle_counter = 0;
} }
} }
state.particles.clear(); state.particles.clear();
// Create sprite instances // Create sprite instances
let (n_object, n_ui) = self.update_sprite_instances(&state); self.update_all_buffers(&state);
// 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.
@ -530,7 +515,11 @@ impl GPUState {
// Sprite pipeline // Sprite pipeline
self.vertex_buffers.object.set_in_pass(&mut render_pass); self.vertex_buffers.object.set_in_pass(&mut render_pass);
render_pass.set_pipeline(&self.object_pipeline); render_pass.set_pipeline(&self.object_pipeline);
render_pass.draw_indexed(0..SPRITE_INDICES.len() as u32, 0, 0..n_object as _); render_pass.draw_indexed(
0..SPRITE_INDICES.len() as u32,
0,
0..self.vertex_buffers.object_counter as _,
);
// Particle pipeline // Particle pipeline
self.vertex_buffers.particle.set_in_pass(&mut render_pass); self.vertex_buffers.particle.set_in_pass(&mut render_pass);
@ -544,13 +533,21 @@ impl GPUState {
// Ui pipeline // Ui pipeline
self.vertex_buffers.ui.set_in_pass(&mut render_pass); self.vertex_buffers.ui.set_in_pass(&mut render_pass);
render_pass.set_pipeline(&self.ui_pipeline); render_pass.set_pipeline(&self.ui_pipeline);
render_pass.draw_indexed(0..SPRITE_INDICES.len() as u32, 0, 0..n_ui as _); render_pass.draw_indexed(
0..SPRITE_INDICES.len() as u32,
0,
0..self.vertex_buffers.ui_counter as _,
);
// Radial progress bars // Radial progress bars
// TODO: do we need to do this every time? // TODO: do we need to do this every time?
self.vertex_buffers.radialbar.set_in_pass(&mut render_pass); self.vertex_buffers.radialbar.set_in_pass(&mut render_pass);
render_pass.set_pipeline(&self.radialbar_pipeline); render_pass.set_pipeline(&self.radialbar_pipeline);
render_pass.draw_indexed(0..SPRITE_INDICES.len() as u32, 0, 0..2); render_pass.draw_indexed(
0..SPRITE_INDICES.len() as u32,
0,
0..self.vertex_buffers.radialbar_counter as _,
);
// begin_render_pass borrows encoder mutably, so we can't call finish() // begin_render_pass borrows encoder mutably, so we can't call finish()
// without dropping this variable. // without dropping this variable.

View File

@ -8,17 +8,18 @@ use galactica_world::{
}; };
use crate::{ use crate::{
globaluniform::ObjectData, vertexbuffer::types::ObjectInstance, GPUState, RenderState, globaluniform::ObjectData,
vertexbuffer::{types::ObjectInstance, BufferObject},
GPUState, RenderState,
}; };
impl GPUState { impl GPUState {
pub(super) fn world_push_ship( pub(super) fn world_push_ship(
&self, &mut self,
state: &RenderState, state: &RenderState,
// NE and SW corners of screen // NE and SW corners of screen
screen_clip: (Point2<f32>, Point2<f32>), screen_clip: (Point2<f32>, Point2<f32>),
s: &ShipWorldObject, s: &ShipWorldObject,
instances: &mut Vec<ObjectInstance>,
) { ) {
let (_, r) = state.world.get_ship_body(s.physics_handle).unwrap(); let (_, r) = state.world.get_ship_body(s.physics_handle).unwrap();
let ship_pos = util::rigidbody_position(&r); let ship_pos = util::rigidbody_position(&r);
@ -47,7 +48,7 @@ impl GPUState {
return; return;
} }
let idx = instances.len(); let idx = self.vertex_buffers.object_counter;
// Write this object's location data // Write this object's location data
self.queue.write_buffer( self.queue.write_buffer(
&self.global_uniform.object_buffer, &self.global_uniform.object_buffer,
@ -64,11 +65,24 @@ impl GPUState {
}]), }]),
); );
// Enforce buffer limit
if self.vertex_buffers.object_counter as u64
> galactica_constants::OBJECT_SPRITE_INSTANCE_LIMIT
{
// TODO: no panic, handle this better.
panic!("Sprite limit exceeded!")
}
// Push this object's instance // Push this object's instance
instances.push(ObjectInstance { self.queue.write_buffer(
sprite_index: ship_cnt.sprite.get_index(), &self.vertex_buffers.object.instances,
object_index: idx as u32, ObjectInstance::SIZE * self.vertex_buffers.object_counter,
}); bytemuck::cast_slice(&[ObjectInstance {
sprite_index: ship_cnt.sprite.get_index(),
object_index: idx as u32,
}]),
);
self.vertex_buffers.object_counter += 1;
// Draw engine flares if necessary // Draw engine flares if necessary
if s.controls.thrust { if s.controls.thrust {
@ -80,7 +94,7 @@ impl GPUState {
self.queue.write_buffer( self.queue.write_buffer(
&self.global_uniform.object_buffer, &self.global_uniform.object_buffer,
ObjectData::SIZE * instances.len() as u64, ObjectData::SIZE * self.vertex_buffers.object_counter as u64,
bytemuck::cast_slice(&[ObjectData { bytemuck::cast_slice(&[ObjectData {
xpos: f.pos.x, xpos: f.pos.x,
ypos: f.pos.y - f.size / 2.0, ypos: f.pos.y - f.size / 2.0,
@ -93,21 +107,33 @@ impl GPUState {
}]), }]),
); );
instances.push(ObjectInstance { // Enforce buffer limit
sprite_index: flare.get_index(), if self.vertex_buffers.object_counter as u64
object_index: instances.len() as u32, > galactica_constants::OBJECT_SPRITE_INSTANCE_LIMIT
}); {
// TODO: no panic, handle this better.
panic!("Sprite limit exceeded!")
}
self.queue.write_buffer(
&self.vertex_buffers.object.instances,
ObjectInstance::SIZE * self.vertex_buffers.object_counter,
bytemuck::cast_slice(&[ObjectInstance {
sprite_index: flare.get_index(),
object_index: self.vertex_buffers.object_counter as u32,
}]),
);
self.vertex_buffers.object_counter += 1;
} }
} }
} }
pub(super) fn world_push_projectile( pub(super) fn world_push_projectile(
&self, &mut self,
state: &RenderState, state: &RenderState,
// NE and SW corners of screen // NE and SW corners of screen
screen_clip: (Point2<f32>, Point2<f32>), screen_clip: (Point2<f32>, Point2<f32>),
p: &ProjectileWorldObject, p: &ProjectileWorldObject,
instances: &mut Vec<ObjectInstance>,
) { ) {
let r = state.world.get_rigid_body(p.rigid_body).unwrap(); let r = state.world.get_rigid_body(p.rigid_body).unwrap();
let proj_pos = util::rigidbody_position(&r); let proj_pos = util::rigidbody_position(&r);
@ -136,7 +162,7 @@ impl GPUState {
return; return;
} }
let idx = instances.len(); let idx = self.vertex_buffers.object_counter;
// Write this object's location data // Write this object's location data
self.queue.write_buffer( self.queue.write_buffer(
&self.global_uniform.object_buffer, &self.global_uniform.object_buffer,
@ -153,10 +179,23 @@ impl GPUState {
}]), }]),
); );
// Enforce buffer limit
if self.vertex_buffers.object_counter as u64
> galactica_constants::OBJECT_SPRITE_INSTANCE_LIMIT
{
// TODO: no panic, handle this better.
panic!("Sprite limit exceeded!")
}
// Push this object's instance // Push this object's instance
instances.push(ObjectInstance { self.queue.write_buffer(
sprite_index: proj_cnt.sprite.get_index(), &self.vertex_buffers.object.instances,
object_index: idx as u32, ObjectInstance::SIZE * self.vertex_buffers.object_counter,
}); bytemuck::cast_slice(&[ObjectInstance {
sprite_index: proj_cnt.sprite.get_index(),
object_index: idx as u32,
}]),
);
self.vertex_buffers.object_counter += 1;
} }
} }