Minor reorganization
parent
246079b33a
commit
3561baa99c
|
@ -44,7 +44,7 @@ impl<'a> Game {
|
||||||
ShipHandle { index: 0 },
|
ShipHandle { index: 0 },
|
||||||
FactionHandle { index: 0 },
|
FactionHandle { index: 0 },
|
||||||
ShipPersonality::Player,
|
ShipPersonality::Player,
|
||||||
Point2::new(0.0, 0.0),
|
Point2::new(0.0, 4000.0),
|
||||||
);
|
);
|
||||||
|
|
||||||
let s = self.state.systemsim.get_ship_mut(&player).unwrap();
|
let s = self.state.systemsim.get_ship_mut(&player).unwrap();
|
||||||
|
|
|
@ -28,6 +28,12 @@ fn anchor(
|
||||||
} else if anchor == 5u { // NE NE
|
} else if anchor == 5u { // NE NE
|
||||||
trans += vec2(window_dim.x, window_dim.y) / 2.0;
|
trans += vec2(window_dim.x, window_dim.y) / 2.0;
|
||||||
trans += vec2(-dim.x, -dim.y) / 2.0;
|
trans += vec2(-dim.x, -dim.y) / 2.0;
|
||||||
|
} else if anchor == 6u { // C C
|
||||||
|
trans += vec2(0.0, 0.0) / 2.0;
|
||||||
|
trans += vec2(0.0, 0.0) / 2.0;
|
||||||
|
} else if anchor == 7u { // C NW
|
||||||
|
trans += vec2(0.0, 0.0) / 2.0;
|
||||||
|
trans += vec2(dim.x, -dim.y) / 2.0;
|
||||||
} else { // center / center as default, since it's the most visible variant.
|
} else { // center / center as default, since it's the most visible variant.
|
||||||
trans += vec2(0.0, 0.0) / 2.0;
|
trans += vec2(0.0, 0.0) / 2.0;
|
||||||
trans += vec2(0.0, 0.0) / 2.0;
|
trans += vec2(0.0, 0.0) / 2.0;
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
use galactica_content::{Content, SystemHandle};
|
|
||||||
use galactica_playeragent::PlayerAgent;
|
|
||||||
use galactica_system::phys::{ParticleBuilder, PhysSim};
|
|
||||||
use galactica_util::timing::Timing;
|
|
||||||
use glyphon::{FontSystem, SwashCache, TextAtlas, TextRenderer};
|
|
||||||
use nalgebra::Vector2;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use wgpu::BufferAddress;
|
|
||||||
use winit::window::Window;
|
|
||||||
|
|
||||||
use crate::{globaluniform::GlobalUniform, vertexbuffer::VertexBuffer};
|
|
||||||
|
|
||||||
/// Bundles parameters passed to a single call to GPUState::render
|
|
||||||
pub struct RenderInput<'a> {
|
|
||||||
/// Camera position, in world units
|
|
||||||
pub camera_pos: Vector2<f32>,
|
|
||||||
|
|
||||||
/// Player ship data
|
|
||||||
pub player: &'a PlayerAgent,
|
|
||||||
|
|
||||||
/// The system we're currently in
|
|
||||||
pub current_system: SystemHandle,
|
|
||||||
|
|
||||||
/// Height of screen, in world units
|
|
||||||
pub camera_zoom: f32,
|
|
||||||
|
|
||||||
/// The world state to render
|
|
||||||
pub systemsim: &'a PhysSim,
|
|
||||||
|
|
||||||
// TODO: handle overflow. is it a problem?
|
|
||||||
/// The current time, in seconds
|
|
||||||
pub current_time: f32,
|
|
||||||
|
|
||||||
/// Game content
|
|
||||||
pub ct: &'a Content,
|
|
||||||
|
|
||||||
/// Particles to spawn during this frame
|
|
||||||
pub particles: &'a Vec<ParticleBuilder>,
|
|
||||||
|
|
||||||
/// Time we spent in each part of the game loop
|
|
||||||
pub timing: Timing,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Renderer state. A reference to this struct is often passed to helper functions.
|
|
||||||
pub(crate) struct RenderState {
|
|
||||||
pub window: Window,
|
|
||||||
pub window_size: winit::dpi::PhysicalSize<u32>,
|
|
||||||
pub window_aspect: f32,
|
|
||||||
|
|
||||||
pub queue: wgpu::Queue,
|
|
||||||
pub global_uniform: GlobalUniform,
|
|
||||||
pub vertex_buffers: VertexBuffers,
|
|
||||||
|
|
||||||
pub text_font_system: FontSystem,
|
|
||||||
pub text_cache: SwashCache,
|
|
||||||
pub text_atlas: TextAtlas,
|
|
||||||
pub text_renderer: TextRenderer,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Vertex buffers
|
|
||||||
pub(crate) struct VertexBuffers {
|
|
||||||
// Keeps track of length of each buffer
|
|
||||||
// Most of these are reset on each frame.
|
|
||||||
//
|
|
||||||
// The exception is particle_counter, which
|
|
||||||
// is never reset, and loops back to zero once
|
|
||||||
// it exceeds buffer length
|
|
||||||
pub object_counter: BufferAddress,
|
|
||||||
pub ui_counter: BufferAddress,
|
|
||||||
pub particle_counter: BufferAddress,
|
|
||||||
pub radialbar_counter: BufferAddress,
|
|
||||||
|
|
||||||
pub object: Rc<VertexBuffer>,
|
|
||||||
pub starfield: Rc<VertexBuffer>,
|
|
||||||
pub ui: Rc<VertexBuffer>,
|
|
||||||
pub particle: Rc<VertexBuffer>,
|
|
||||||
pub radialbar: Rc<VertexBuffer>,
|
|
||||||
}
|
|
|
@ -3,9 +3,7 @@ use galactica_content::Content;
|
||||||
use wgpu;
|
use wgpu;
|
||||||
use winit;
|
use winit;
|
||||||
|
|
||||||
use crate::{
|
use crate::{starfield::Starfield, texturearray::TextureArray, ui::UiManager, RenderState};
|
||||||
datastructs::RenderState, starfield::Starfield, texturearray::TextureArray, ui::UiManager,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// GPUState is very big, so its methods have been split
|
/// GPUState is very big, so its methods have been split
|
||||||
/// among the following files.
|
/// among the following files.
|
||||||
|
|
|
@ -1,28 +1,11 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use galactica_content::Content;
|
use galactica_content::Content;
|
||||||
use galactica_util::constants::{
|
|
||||||
OBJECT_SPRITE_INSTANCE_LIMIT, PARTICLE_SPRITE_INSTANCE_LIMIT, UI_SPRITE_INSTANCE_LIMIT,
|
|
||||||
};
|
|
||||||
use glyphon::{FontSystem, SwashCache, TextAtlas, TextRenderer};
|
use glyphon::{FontSystem, SwashCache, TextAtlas, TextRenderer};
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
datastructs::{RenderState, VertexBuffers},
|
globaluniform::GlobalUniform, pipeline::PipelineBuilder, shaderprocessor::preprocess_shader,
|
||||||
globaluniform::GlobalUniform,
|
starfield::Starfield, texturearray::TextureArray, ui::UiManager, GPUState, RenderState,
|
||||||
pipeline::PipelineBuilder,
|
VertexBuffers,
|
||||||
shaderprocessor::preprocess_shader,
|
|
||||||
starfield::Starfield,
|
|
||||||
texturearray::TextureArray,
|
|
||||||
ui::UiManager,
|
|
||||||
vertexbuffer::{
|
|
||||||
consts::{SPRITE_INDICES, SPRITE_VERTICES},
|
|
||||||
types::{
|
|
||||||
ObjectInstance, ParticleInstance, RadialBarInstance, StarfieldInstance, TexturedVertex,
|
|
||||||
UiInstance,
|
|
||||||
},
|
|
||||||
VertexBuffer,
|
|
||||||
},
|
|
||||||
GPUState,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl GPUState {
|
impl GPUState {
|
||||||
|
@ -90,52 +73,7 @@ impl GPUState {
|
||||||
surface.configure(&device, &config);
|
surface.configure(&device, &config);
|
||||||
}
|
}
|
||||||
|
|
||||||
let vertex_buffers = VertexBuffers {
|
let vertex_buffers = VertexBuffers::new(&device, ct);
|
||||||
object_counter: 0,
|
|
||||||
ui_counter: 0,
|
|
||||||
particle_counter: 0,
|
|
||||||
radialbar_counter: 0,
|
|
||||||
|
|
||||||
object: Rc::new(VertexBuffer::new::<TexturedVertex, ObjectInstance>(
|
|
||||||
"object",
|
|
||||||
&device,
|
|
||||||
Some(SPRITE_VERTICES),
|
|
||||||
Some(SPRITE_INDICES),
|
|
||||||
OBJECT_SPRITE_INSTANCE_LIMIT,
|
|
||||||
)),
|
|
||||||
|
|
||||||
starfield: Rc::new(VertexBuffer::new::<TexturedVertex, StarfieldInstance>(
|
|
||||||
"starfield",
|
|
||||||
&device,
|
|
||||||
Some(SPRITE_VERTICES),
|
|
||||||
Some(SPRITE_INDICES),
|
|
||||||
ct.get_config().starfield_instance_limit,
|
|
||||||
)),
|
|
||||||
|
|
||||||
ui: Rc::new(VertexBuffer::new::<TexturedVertex, UiInstance>(
|
|
||||||
"ui",
|
|
||||||
&device,
|
|
||||||
Some(SPRITE_VERTICES),
|
|
||||||
Some(SPRITE_INDICES),
|
|
||||||
UI_SPRITE_INSTANCE_LIMIT,
|
|
||||||
)),
|
|
||||||
|
|
||||||
particle: Rc::new(VertexBuffer::new::<TexturedVertex, ParticleInstance>(
|
|
||||||
"particle",
|
|
||||||
&device,
|
|
||||||
Some(SPRITE_VERTICES),
|
|
||||||
Some(SPRITE_INDICES),
|
|
||||||
PARTICLE_SPRITE_INSTANCE_LIMIT,
|
|
||||||
)),
|
|
||||||
|
|
||||||
radialbar: Rc::new(VertexBuffer::new::<TexturedVertex, RadialBarInstance>(
|
|
||||||
"radial bar",
|
|
||||||
&device,
|
|
||||||
Some(SPRITE_VERTICES),
|
|
||||||
Some(SPRITE_INDICES),
|
|
||||||
10,
|
|
||||||
)),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Load uniforms
|
// Load uniforms
|
||||||
let global_uniform = GlobalUniform::new(&device);
|
let global_uniform = GlobalUniform::new(&device);
|
||||||
|
@ -197,7 +135,7 @@ impl GPUState {
|
||||||
))
|
))
|
||||||
.set_format(config.format)
|
.set_format(config.format)
|
||||||
.set_triangle(true)
|
.set_triangle(true)
|
||||||
.set_vertex_buffer(&vertex_buffers.object)
|
.set_vertex_buffer(vertex_buffers.get_object())
|
||||||
.set_bind_group_layouts(bind_group_layouts)
|
.set_bind_group_layouts(bind_group_layouts)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -213,7 +151,7 @@ impl GPUState {
|
||||||
))
|
))
|
||||||
.set_format(config.format)
|
.set_format(config.format)
|
||||||
.set_triangle(true)
|
.set_triangle(true)
|
||||||
.set_vertex_buffer(&vertex_buffers.starfield)
|
.set_vertex_buffer(vertex_buffers.get_starfield())
|
||||||
.set_bind_group_layouts(bind_group_layouts)
|
.set_bind_group_layouts(bind_group_layouts)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -225,7 +163,7 @@ impl GPUState {
|
||||||
))
|
))
|
||||||
.set_format(config.format)
|
.set_format(config.format)
|
||||||
.set_triangle(true)
|
.set_triangle(true)
|
||||||
.set_vertex_buffer(&vertex_buffers.ui)
|
.set_vertex_buffer(vertex_buffers.get_ui())
|
||||||
.set_bind_group_layouts(bind_group_layouts)
|
.set_bind_group_layouts(bind_group_layouts)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -241,7 +179,7 @@ impl GPUState {
|
||||||
))
|
))
|
||||||
.set_format(config.format)
|
.set_format(config.format)
|
||||||
.set_triangle(true)
|
.set_triangle(true)
|
||||||
.set_vertex_buffer(&vertex_buffers.particle)
|
.set_vertex_buffer(vertex_buffers.get_particle())
|
||||||
.set_bind_group_layouts(bind_group_layouts)
|
.set_bind_group_layouts(bind_group_layouts)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -257,7 +195,7 @@ impl GPUState {
|
||||||
))
|
))
|
||||||
.set_format(config.format)
|
.set_format(config.format)
|
||||||
.set_triangle(true)
|
.set_triangle(true)
|
||||||
.set_vertex_buffer(&vertex_buffers.radialbar)
|
.set_vertex_buffer(vertex_buffers.get_radialbar())
|
||||||
.set_bind_group_layouts(bind_group_layouts)
|
.set_bind_group_layouts(bind_group_layouts)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -281,7 +219,7 @@ impl GPUState {
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(Self {
|
return Ok(Self {
|
||||||
ui: UiManager::new(&mut state),
|
ui: UiManager::new(ct, &mut state),
|
||||||
device,
|
device,
|
||||||
config,
|
config,
|
||||||
surface,
|
surface,
|
||||||
|
|
|
@ -2,13 +2,11 @@
|
||||||
|
|
||||||
use bytemuck;
|
use bytemuck;
|
||||||
use galactica_system::data::ShipState;
|
use galactica_system::data::ShipState;
|
||||||
use galactica_util::{constants::OBJECT_SPRITE_INSTANCE_LIMIT, to_radians};
|
use galactica_util::to_radians;
|
||||||
use nalgebra::{Point2, Point3};
|
use nalgebra::{Point2, Point3};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
globaluniform::ObjectData,
|
globaluniform::ObjectData, vertexbuffer::types::ObjectInstance, GPUState, RenderInput,
|
||||||
vertexbuffer::{types::ObjectInstance, BufferObject},
|
|
||||||
GPUState, RenderInput,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl GPUState {
|
impl GPUState {
|
||||||
|
@ -68,7 +66,7 @@ impl GPUState {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let idx = self.state.vertex_buffers.object_counter;
|
let idx = self.state.get_object_counter();
|
||||||
// Write this object's location data
|
// Write this object's location data
|
||||||
self.state.queue.write_buffer(
|
self.state.queue.write_buffer(
|
||||||
&self.state.global_uniform.object_buffer,
|
&self.state.global_uniform.object_buffer,
|
||||||
|
@ -85,22 +83,11 @@ impl GPUState {
|
||||||
}]),
|
}]),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Enforce buffer limit
|
|
||||||
if self.state.vertex_buffers.object_counter as u64 > OBJECT_SPRITE_INSTANCE_LIMIT {
|
|
||||||
// TODO: no panic, handle this better.
|
|
||||||
panic!("Sprite limit exceeded!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push this object's instance
|
// Push this object's instance
|
||||||
self.state.queue.write_buffer(
|
self.state.push_object_buffer(ObjectInstance {
|
||||||
&self.state.vertex_buffers.object.instances,
|
|
||||||
ObjectInstance::SIZE * self.state.vertex_buffers.object_counter,
|
|
||||||
bytemuck::cast_slice(&[ObjectInstance {
|
|
||||||
sprite_index: ship_cnt.sprite.get_index(),
|
sprite_index: ship_cnt.sprite.get_index(),
|
||||||
object_index: idx as u32,
|
object_index: idx as u32,
|
||||||
}]),
|
});
|
||||||
);
|
|
||||||
self.state.vertex_buffers.object_counter += 1;
|
|
||||||
|
|
||||||
let flare = ship.data.get_outfits().get_flare_sprite(state.ct);
|
let flare = ship.data.get_outfits().get_flare_sprite(state.ct);
|
||||||
if {
|
if {
|
||||||
|
@ -115,7 +102,7 @@ impl GPUState {
|
||||||
for engine_point in &ship_cnt.engines {
|
for engine_point in &ship_cnt.engines {
|
||||||
self.state.queue.write_buffer(
|
self.state.queue.write_buffer(
|
||||||
&self.state.global_uniform.object_buffer,
|
&self.state.global_uniform.object_buffer,
|
||||||
ObjectData::SIZE * self.state.vertex_buffers.object_counter as u64,
|
ObjectData::SIZE * self.state.get_object_counter() as u64,
|
||||||
bytemuck::cast_slice(&[ObjectData {
|
bytemuck::cast_slice(&[ObjectData {
|
||||||
// Note that we adjust the y-coordinate for half-height,
|
// Note that we adjust the y-coordinate for half-height,
|
||||||
// not the x-coordinate, even though our ships point east
|
// not the x-coordinate, even though our ships point east
|
||||||
|
@ -135,23 +122,10 @@ impl GPUState {
|
||||||
}]),
|
}]),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Enforce buffer limit
|
self.state.push_object_buffer(ObjectInstance {
|
||||||
if self.state.vertex_buffers.object_counter as u64
|
|
||||||
> OBJECT_SPRITE_INSTANCE_LIMIT
|
|
||||||
{
|
|
||||||
// TODO: no panic, handle this better.
|
|
||||||
panic!("Sprite limit exceeded!")
|
|
||||||
}
|
|
||||||
|
|
||||||
self.state.queue.write_buffer(
|
|
||||||
&self.state.vertex_buffers.object.instances,
|
|
||||||
ObjectInstance::SIZE * self.state.vertex_buffers.object_counter,
|
|
||||||
bytemuck::cast_slice(&[ObjectInstance {
|
|
||||||
sprite_index: flare.unwrap().get_index(),
|
sprite_index: flare.unwrap().get_index(),
|
||||||
object_index: self.state.vertex_buffers.object_counter as u32,
|
object_index: self.state.get_object_counter() as u32,
|
||||||
}]),
|
});
|
||||||
);
|
|
||||||
self.state.vertex_buffers.object_counter += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +165,7 @@ impl GPUState {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let idx = self.state.vertex_buffers.object_counter;
|
let idx = self.state.get_object_counter();
|
||||||
// Write this object's location data
|
// Write this object's location data
|
||||||
self.state.queue.write_buffer(
|
self.state.queue.write_buffer(
|
||||||
&self.state.global_uniform.object_buffer,
|
&self.state.global_uniform.object_buffer,
|
||||||
|
@ -208,22 +182,11 @@ impl GPUState {
|
||||||
}]),
|
}]),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Enforce buffer limit
|
|
||||||
if self.state.vertex_buffers.object_counter as u64 > OBJECT_SPRITE_INSTANCE_LIMIT {
|
|
||||||
// TODO: no panic, handle this better.
|
|
||||||
panic!("Sprite limit exceeded!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push this object's instance
|
// Push this object's instance
|
||||||
self.state.queue.write_buffer(
|
self.state.push_object_buffer(ObjectInstance {
|
||||||
&self.state.vertex_buffers.object.instances,
|
|
||||||
ObjectInstance::SIZE * self.state.vertex_buffers.object_counter,
|
|
||||||
bytemuck::cast_slice(&[ObjectInstance {
|
|
||||||
sprite_index: proj_cnt.sprite.get_index(),
|
sprite_index: proj_cnt.sprite.get_index(),
|
||||||
object_index: idx as u32,
|
object_index: idx as u32,
|
||||||
}]),
|
});
|
||||||
);
|
|
||||||
self.state.vertex_buffers.object_counter += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +218,7 @@ impl GPUState {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let idx = self.state.vertex_buffers.object_counter;
|
let idx = self.state.get_object_counter();
|
||||||
// Write this object's location data
|
// Write this object's location data
|
||||||
self.state.queue.write_buffer(
|
self.state.queue.write_buffer(
|
||||||
&self.state.global_uniform.object_buffer,
|
&self.state.global_uniform.object_buffer,
|
||||||
|
@ -272,22 +235,11 @@ impl GPUState {
|
||||||
}]),
|
}]),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Enforce buffer limit
|
|
||||||
if self.state.vertex_buffers.object_counter as u64 > OBJECT_SPRITE_INSTANCE_LIMIT {
|
|
||||||
// TODO: no panic, handle this better.
|
|
||||||
panic!("Sprite limit exceeded!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push this object's instance
|
// Push this object's instance
|
||||||
self.state.queue.write_buffer(
|
self.state.push_object_buffer(ObjectInstance {
|
||||||
&self.state.vertex_buffers.object.instances,
|
|
||||||
ObjectInstance::SIZE * self.state.vertex_buffers.object_counter,
|
|
||||||
bytemuck::cast_slice(&[ObjectInstance {
|
|
||||||
sprite_index: o.sprite.get_index(),
|
sprite_index: o.sprite.get_index(),
|
||||||
object_index: idx as u32,
|
object_index: idx as u32,
|
||||||
}]),
|
});
|
||||||
);
|
|
||||||
self.state.vertex_buffers.object_counter += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use wgpu;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
globaluniform::GlobalDataContent,
|
globaluniform::GlobalDataContent,
|
||||||
vertexbuffer::{consts::SPRITE_INDICES, types::ParticleInstance, BufferObject},
|
vertexbuffer::{consts::SPRITE_INDICES, types::ParticleInstance},
|
||||||
RenderInput,
|
RenderInput,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,11 +45,7 @@ impl super::GPUState {
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.state.vertex_buffers.object_counter = 0;
|
self.state.frame_reset();
|
||||||
self.state.vertex_buffers.ui_counter = 0;
|
|
||||||
self.state.vertex_buffers.radialbar_counter = 0;
|
|
||||||
// Don't reset particle counter, it's special
|
|
||||||
|
|
||||||
let s = input.ct.get_starfield_handle();
|
let s = input.ct.get_starfield_handle();
|
||||||
|
|
||||||
// Update global values
|
// Update global values
|
||||||
|
@ -81,10 +77,7 @@ impl super::GPUState {
|
||||||
|
|
||||||
// Write all new particles to GPU buffer
|
// Write all new particles to GPU buffer
|
||||||
for i in input.particles.iter() {
|
for i in input.particles.iter() {
|
||||||
self.state.queue.write_buffer(
|
self.state.push_particle_buffer(ParticleInstance {
|
||||||
&self.state.vertex_buffers.particle.instances,
|
|
||||||
ParticleInstance::SIZE * self.state.vertex_buffers.particle_counter,
|
|
||||||
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(),
|
||||||
angle: i.angle,
|
angle: i.angle,
|
||||||
|
@ -94,12 +87,7 @@ impl super::GPUState {
|
||||||
created: input.current_time,
|
created: input.current_time,
|
||||||
expires: input.current_time + i.lifetime,
|
expires: input.current_time + i.lifetime,
|
||||||
fade: i.fade,
|
fade: i.fade,
|
||||||
}]),
|
});
|
||||||
);
|
|
||||||
self.state.vertex_buffers.particle_counter += 1;
|
|
||||||
if self.state.vertex_buffers.particle_counter == PARTICLE_SPRITE_INSTANCE_LIMIT {
|
|
||||||
self.state.vertex_buffers.particle_counter = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create sprite instances
|
// Create sprite instances
|
||||||
|
@ -109,10 +97,6 @@ impl super::GPUState {
|
||||||
let clip_ne = Point2::new(-self.state.window_aspect, 1.0) * input.camera_zoom;
|
let clip_ne = Point2::new(-self.state.window_aspect, 1.0) * input.camera_zoom;
|
||||||
let clip_sw = Point2::new(self.state.window_aspect, -1.0) * input.camera_zoom;
|
let clip_sw = Point2::new(self.state.window_aspect, -1.0) * input.camera_zoom;
|
||||||
|
|
||||||
// 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.
|
// Order matters, it determines what is drawn on top.
|
||||||
// The order inside ships and projectiles doesn't matter,
|
// The order inside ships and projectiles doesn't matter,
|
||||||
// but ships should always be under projectiles.
|
// but ships should always be under projectiles.
|
||||||
|
@ -129,31 +113,31 @@ impl super::GPUState {
|
||||||
// Starfield pipeline
|
// Starfield pipeline
|
||||||
self.state
|
self.state
|
||||||
.vertex_buffers
|
.vertex_buffers
|
||||||
.starfield
|
.get_starfield()
|
||||||
.set_in_pass(&mut render_pass);
|
.set_in_pass(&mut render_pass);
|
||||||
render_pass.set_pipeline(&self.starfield_pipeline);
|
render_pass.set_pipeline(&self.starfield_pipeline);
|
||||||
render_pass.draw_indexed(
|
render_pass.draw_indexed(
|
||||||
0..SPRITE_INDICES.len() as u32,
|
0..SPRITE_INDICES.len() as u32,
|
||||||
0,
|
0,
|
||||||
0..self.starfield.instance_count,
|
0..self.state.get_starfield_counter(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Sprite pipeline
|
// Sprite pipeline
|
||||||
self.state
|
self.state
|
||||||
.vertex_buffers
|
.vertex_buffers
|
||||||
.object
|
.get_object()
|
||||||
.set_in_pass(&mut render_pass);
|
.set_in_pass(&mut render_pass);
|
||||||
render_pass.set_pipeline(&self.object_pipeline);
|
render_pass.set_pipeline(&self.object_pipeline);
|
||||||
render_pass.draw_indexed(
|
render_pass.draw_indexed(
|
||||||
0..SPRITE_INDICES.len() as u32,
|
0..SPRITE_INDICES.len() as u32,
|
||||||
0,
|
0,
|
||||||
0..self.state.vertex_buffers.object_counter as _,
|
0..self.state.get_object_counter(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Particle pipeline
|
// Particle pipeline
|
||||||
self.state
|
self.state
|
||||||
.vertex_buffers
|
.vertex_buffers
|
||||||
.particle
|
.get_particle()
|
||||||
.set_in_pass(&mut render_pass);
|
.set_in_pass(&mut render_pass);
|
||||||
render_pass.set_pipeline(&self.particle_pipeline);
|
render_pass.set_pipeline(&self.particle_pipeline);
|
||||||
render_pass.draw_indexed(
|
render_pass.draw_indexed(
|
||||||
|
@ -163,27 +147,31 @@ impl super::GPUState {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ui pipeline
|
// Ui pipeline
|
||||||
self.state.vertex_buffers.ui.set_in_pass(&mut render_pass);
|
self.state
|
||||||
|
.vertex_buffers
|
||||||
|
.get_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(
|
render_pass.draw_indexed(
|
||||||
0..SPRITE_INDICES.len() as u32,
|
0..SPRITE_INDICES.len() as u32,
|
||||||
0,
|
0,
|
||||||
0..self.state.vertex_buffers.ui_counter as _,
|
0..self.state.get_ui_counter(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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.state
|
self.state
|
||||||
.vertex_buffers
|
.vertex_buffers
|
||||||
.radialbar
|
.get_radialbar()
|
||||||
.set_in_pass(&mut render_pass);
|
.set_in_pass(&mut render_pass);
|
||||||
render_pass.set_pipeline(&self.radialbar_pipeline);
|
render_pass.set_pipeline(&self.radialbar_pipeline);
|
||||||
render_pass.draw_indexed(
|
render_pass.draw_indexed(
|
||||||
0..SPRITE_INDICES.len() as u32,
|
0..SPRITE_INDICES.len() as u32,
|
||||||
0,
|
0,
|
||||||
0..self.state.vertex_buffers.radialbar_counter as _,
|
0..self.state.get_radialbar_counter(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let textareas = self.ui.get_textareas(&input, &self.state);
|
||||||
self.state
|
self.state
|
||||||
.text_renderer
|
.text_renderer
|
||||||
.prepare(
|
.prepare(
|
||||||
|
@ -195,7 +183,7 @@ impl super::GPUState {
|
||||||
width: self.state.window_size.width,
|
width: self.state.window_size.width,
|
||||||
height: self.state.window_size.height,
|
height: self.state.window_size.height,
|
||||||
},
|
},
|
||||||
self.ui.get_textareas(),
|
textareas,
|
||||||
&mut self.state.text_cache,
|
&mut self.state.text_cache,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -7,20 +7,24 @@
|
||||||
//! and the only one external code should interact with.
|
//! and the only one external code should interact with.
|
||||||
//! (Excluding data structs, like [`ObjectSprite`])
|
//! (Excluding data structs, like [`ObjectSprite`])
|
||||||
|
|
||||||
mod anchoredposition;
|
|
||||||
mod datastructs;
|
|
||||||
mod globaluniform;
|
mod globaluniform;
|
||||||
mod gpustate;
|
mod gpustate;
|
||||||
mod pipeline;
|
mod pipeline;
|
||||||
|
mod positionanchor;
|
||||||
|
mod renderinput;
|
||||||
|
mod renderstate;
|
||||||
mod shaderprocessor;
|
mod shaderprocessor;
|
||||||
mod starfield;
|
mod starfield;
|
||||||
mod texturearray;
|
mod texturearray;
|
||||||
mod ui;
|
mod ui;
|
||||||
mod vertexbuffer;
|
mod vertexbuffer;
|
||||||
|
|
||||||
pub use anchoredposition::PositionAnchor;
|
use renderstate::*;
|
||||||
pub use datastructs::RenderInput;
|
|
||||||
pub use gpustate::GPUState;
|
pub use gpustate::GPUState;
|
||||||
|
pub use positionanchor::PositionAnchor;
|
||||||
|
pub use renderinput::RenderInput;
|
||||||
|
|
||||||
use nalgebra::Matrix4;
|
use nalgebra::Matrix4;
|
||||||
|
|
||||||
/// Shader entry points
|
/// Shader entry points
|
||||||
|
|
|
@ -28,6 +28,14 @@ pub enum PositionAnchor {
|
||||||
/// Position of this sprite's ne corner,
|
/// Position of this sprite's ne corner,
|
||||||
/// relative to the ne corner of the window.
|
/// relative to the ne corner of the window.
|
||||||
NeNe,
|
NeNe,
|
||||||
|
|
||||||
|
/// Position of this sprite's center,
|
||||||
|
/// relative to the center of the window.
|
||||||
|
CC,
|
||||||
|
|
||||||
|
/// Position of this sprite's NW corner,
|
||||||
|
/// relative to the center of the window.
|
||||||
|
CNw,
|
||||||
}
|
}
|
||||||
|
|
||||||
// These offsets are implemented in wgsl shaders.
|
// These offsets are implemented in wgsl shaders.
|
||||||
|
@ -42,6 +50,8 @@ impl PositionAnchor {
|
||||||
Self::NwSw => 3,
|
Self::NwSw => 3,
|
||||||
Self::NwSe => 4,
|
Self::NwSe => 4,
|
||||||
Self::NeNe => 5,
|
Self::NeNe => 5,
|
||||||
|
Self::CC => 6,
|
||||||
|
Self::CNw => 7,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
use galactica_content::{Content, SystemHandle};
|
||||||
|
use galactica_playeragent::PlayerAgent;
|
||||||
|
use galactica_system::phys::{ParticleBuilder, PhysSim};
|
||||||
|
use galactica_util::timing::Timing;
|
||||||
|
use nalgebra::Vector2;
|
||||||
|
|
||||||
|
/// Bundles parameters passed to a single call to GPUState::render
|
||||||
|
pub struct RenderInput<'a> {
|
||||||
|
/// Camera position, in world units
|
||||||
|
pub camera_pos: Vector2<f32>,
|
||||||
|
|
||||||
|
/// Player ship data
|
||||||
|
pub player: &'a PlayerAgent,
|
||||||
|
|
||||||
|
/// The system we're currently in
|
||||||
|
pub current_system: SystemHandle,
|
||||||
|
|
||||||
|
/// Height of screen, in world units
|
||||||
|
pub camera_zoom: f32,
|
||||||
|
|
||||||
|
/// The world state to render
|
||||||
|
pub systemsim: &'a PhysSim,
|
||||||
|
|
||||||
|
// TODO: handle overflow. is it a problem?
|
||||||
|
/// The current time, in seconds
|
||||||
|
pub current_time: f32,
|
||||||
|
|
||||||
|
/// Game content
|
||||||
|
pub ct: &'a Content,
|
||||||
|
|
||||||
|
/// Particles to spawn during this frame
|
||||||
|
pub particles: &'a Vec<ParticleBuilder>,
|
||||||
|
|
||||||
|
/// Time we spent in each part of the game loop
|
||||||
|
pub timing: Timing,
|
||||||
|
}
|
|
@ -0,0 +1,237 @@
|
||||||
|
use galactica_content::Content;
|
||||||
|
use galactica_util::constants::{
|
||||||
|
OBJECT_SPRITE_INSTANCE_LIMIT, PARTICLE_SPRITE_INSTANCE_LIMIT, RADIALBAR_SPRITE_INSTANCE_LIMIT,
|
||||||
|
UI_SPRITE_INSTANCE_LIMIT,
|
||||||
|
};
|
||||||
|
use glyphon::{FontSystem, SwashCache, TextAtlas, TextRenderer};
|
||||||
|
use std::rc::Rc;
|
||||||
|
use wgpu::BufferAddress;
|
||||||
|
use winit::window::Window;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
globaluniform::GlobalUniform,
|
||||||
|
vertexbuffer::{
|
||||||
|
consts::{SPRITE_INDICES, SPRITE_VERTICES},
|
||||||
|
types::{
|
||||||
|
ObjectInstance, ParticleInstance, RadialBarInstance, StarfieldInstance, TexturedVertex,
|
||||||
|
UiInstance,
|
||||||
|
},
|
||||||
|
BufferObject, VertexBuffer,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Vertex buffers
|
||||||
|
pub(crate) struct VertexBuffers {
|
||||||
|
// Keeps track of length of each buffer
|
||||||
|
// Most of these are reset on each frame.
|
||||||
|
//
|
||||||
|
// The exception is particle_counter, which
|
||||||
|
// is never reset, and loops back to zero once
|
||||||
|
// it exceeds buffer length
|
||||||
|
object_counter: BufferAddress,
|
||||||
|
ui_counter: BufferAddress,
|
||||||
|
particle_counter: BufferAddress,
|
||||||
|
radialbar_counter: BufferAddress,
|
||||||
|
starfield_counter: BufferAddress,
|
||||||
|
starfield_limit: BufferAddress,
|
||||||
|
|
||||||
|
object: Rc<VertexBuffer>,
|
||||||
|
starfield: Rc<VertexBuffer>,
|
||||||
|
ui: Rc<VertexBuffer>,
|
||||||
|
particle: Rc<VertexBuffer>,
|
||||||
|
radialbar: Rc<VertexBuffer>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> VertexBuffers {
|
||||||
|
pub fn new(device: &wgpu::Device, ct: &Content) -> Self {
|
||||||
|
Self {
|
||||||
|
object_counter: 0,
|
||||||
|
ui_counter: 0,
|
||||||
|
particle_counter: 0,
|
||||||
|
radialbar_counter: 0,
|
||||||
|
starfield_counter: 0,
|
||||||
|
starfield_limit: ct.get_config().starfield_instance_limit,
|
||||||
|
|
||||||
|
object: Rc::new(VertexBuffer::new::<TexturedVertex, ObjectInstance>(
|
||||||
|
"object",
|
||||||
|
&device,
|
||||||
|
Some(SPRITE_VERTICES),
|
||||||
|
Some(SPRITE_INDICES),
|
||||||
|
OBJECT_SPRITE_INSTANCE_LIMIT,
|
||||||
|
)),
|
||||||
|
|
||||||
|
starfield: Rc::new(VertexBuffer::new::<TexturedVertex, StarfieldInstance>(
|
||||||
|
"starfield",
|
||||||
|
&device,
|
||||||
|
Some(SPRITE_VERTICES),
|
||||||
|
Some(SPRITE_INDICES),
|
||||||
|
ct.get_config().starfield_instance_limit,
|
||||||
|
)),
|
||||||
|
|
||||||
|
ui: Rc::new(VertexBuffer::new::<TexturedVertex, UiInstance>(
|
||||||
|
"ui",
|
||||||
|
&device,
|
||||||
|
Some(SPRITE_VERTICES),
|
||||||
|
Some(SPRITE_INDICES),
|
||||||
|
UI_SPRITE_INSTANCE_LIMIT,
|
||||||
|
)),
|
||||||
|
|
||||||
|
particle: Rc::new(VertexBuffer::new::<TexturedVertex, ParticleInstance>(
|
||||||
|
"particle",
|
||||||
|
&device,
|
||||||
|
Some(SPRITE_VERTICES),
|
||||||
|
Some(SPRITE_INDICES),
|
||||||
|
PARTICLE_SPRITE_INSTANCE_LIMIT,
|
||||||
|
)),
|
||||||
|
|
||||||
|
radialbar: Rc::new(VertexBuffer::new::<TexturedVertex, RadialBarInstance>(
|
||||||
|
"radial bar",
|
||||||
|
&device,
|
||||||
|
Some(SPRITE_VERTICES),
|
||||||
|
Some(SPRITE_INDICES),
|
||||||
|
10,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_ui(&'a self) -> &'a Rc<VertexBuffer> {
|
||||||
|
&self.ui
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_object(&'a self) -> &'a Rc<VertexBuffer> {
|
||||||
|
&self.object
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_particle(&'a self) -> &'a Rc<VertexBuffer> {
|
||||||
|
&self.particle
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_radialbar(&'a self) -> &'a Rc<VertexBuffer> {
|
||||||
|
&self.radialbar
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_starfield(&'a self) -> &'a Rc<VertexBuffer> {
|
||||||
|
&self.starfield
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Renderer state. A reference to this struct is often passed to helper functions.
|
||||||
|
pub(crate) struct RenderState {
|
||||||
|
pub window: Window,
|
||||||
|
pub window_size: winit::dpi::PhysicalSize<u32>,
|
||||||
|
pub window_aspect: f32,
|
||||||
|
|
||||||
|
pub queue: wgpu::Queue,
|
||||||
|
pub global_uniform: GlobalUniform,
|
||||||
|
pub vertex_buffers: VertexBuffers,
|
||||||
|
|
||||||
|
pub text_font_system: FontSystem,
|
||||||
|
pub text_cache: SwashCache,
|
||||||
|
pub text_atlas: TextAtlas,
|
||||||
|
pub text_renderer: TextRenderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderState {
|
||||||
|
/// Prepare this state for a new frame
|
||||||
|
pub fn frame_reset(&mut self) {
|
||||||
|
self.vertex_buffers.object_counter = 0;
|
||||||
|
self.vertex_buffers.ui_counter = 0;
|
||||||
|
self.vertex_buffers.radialbar_counter = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_ui_buffer(&mut self, instance: UiInstance) {
|
||||||
|
// Enforce buffer limit
|
||||||
|
if self.vertex_buffers.ui_counter as u64 > UI_SPRITE_INSTANCE_LIMIT {
|
||||||
|
// TODO: no panic, handle this better.
|
||||||
|
panic!("UI limit exceeded!")
|
||||||
|
}
|
||||||
|
|
||||||
|
self.queue.write_buffer(
|
||||||
|
&self.vertex_buffers.ui.instances,
|
||||||
|
UiInstance::SIZE * self.vertex_buffers.ui_counter,
|
||||||
|
bytemuck::cast_slice(&[instance]),
|
||||||
|
);
|
||||||
|
self.vertex_buffers.ui_counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_ui_counter(&self) -> u32 {
|
||||||
|
self.vertex_buffers.ui_counter as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_object_buffer(&mut self, instance: ObjectInstance) {
|
||||||
|
// Enforce buffer limit
|
||||||
|
if self.vertex_buffers.object_counter as u64 > OBJECT_SPRITE_INSTANCE_LIMIT {
|
||||||
|
// TODO: no panic, handle this better.
|
||||||
|
panic!("Object limit exceeded!")
|
||||||
|
}
|
||||||
|
|
||||||
|
self.queue.write_buffer(
|
||||||
|
&self.vertex_buffers.object.instances,
|
||||||
|
ObjectInstance::SIZE * self.vertex_buffers.object_counter,
|
||||||
|
bytemuck::cast_slice(&[instance]),
|
||||||
|
);
|
||||||
|
self.vertex_buffers.object_counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_object_counter(&self) -> u32 {
|
||||||
|
self.vertex_buffers.object_counter as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_radialbar_buffer(&mut self, instance: RadialBarInstance) {
|
||||||
|
// Enforce buffer limit
|
||||||
|
if self.vertex_buffers.radialbar_counter as u64 > RADIALBAR_SPRITE_INSTANCE_LIMIT {
|
||||||
|
// TODO: no panic, handle this better.
|
||||||
|
panic!("Radialbar sprite limit exceeded!")
|
||||||
|
}
|
||||||
|
|
||||||
|
self.queue.write_buffer(
|
||||||
|
&self.vertex_buffers.radialbar.instances,
|
||||||
|
RadialBarInstance::SIZE * self.vertex_buffers.radialbar_counter,
|
||||||
|
bytemuck::cast_slice(&[instance]),
|
||||||
|
);
|
||||||
|
self.vertex_buffers.radialbar_counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_radialbar_counter(&self) -> u32 {
|
||||||
|
self.vertex_buffers.radialbar_counter as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_starfield_counter(&mut self) {
|
||||||
|
self.vertex_buffers.starfield_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_starfield_buffer(&mut self, instance: StarfieldInstance) {
|
||||||
|
// Enforce buffer limit
|
||||||
|
// This should never happen, since starfield generator checks array size
|
||||||
|
if self.vertex_buffers.starfield_counter as u64 > self.vertex_buffers.starfield_limit {
|
||||||
|
panic!("Starfield sprite limit exceeded!")
|
||||||
|
}
|
||||||
|
|
||||||
|
self.queue.write_buffer(
|
||||||
|
&self.vertex_buffers.starfield.instances,
|
||||||
|
StarfieldInstance::SIZE * self.vertex_buffers.starfield_counter,
|
||||||
|
bytemuck::cast_slice(&[instance]),
|
||||||
|
);
|
||||||
|
self.vertex_buffers.starfield_counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_starfield_counter(&self) -> u32 {
|
||||||
|
self.vertex_buffers.starfield_counter as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_particle_buffer(&mut self, instance: ParticleInstance) {
|
||||||
|
self.queue.write_buffer(
|
||||||
|
&self.vertex_buffers.particle.instances,
|
||||||
|
ParticleInstance::SIZE * self.vertex_buffers.particle_counter,
|
||||||
|
bytemuck::cast_slice(&[instance]),
|
||||||
|
);
|
||||||
|
self.vertex_buffers.particle_counter += 1;
|
||||||
|
if self.vertex_buffers.particle_counter == PARTICLE_SPRITE_INSTANCE_LIMIT {
|
||||||
|
self.vertex_buffers.particle_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//pub fn get_particle_counter(&self) -> u32 {
|
||||||
|
// self.vertex_buffers.particle_counter as u32
|
||||||
|
//}
|
||||||
|
}
|
|
@ -2,10 +2,7 @@ use galactica_content::Content;
|
||||||
use nalgebra::{Point2, Point3, Vector2, Vector3};
|
use nalgebra::{Point2, Point3, Vector2, Vector3};
|
||||||
use rand::{self, Rng};
|
use rand::{self, Rng};
|
||||||
|
|
||||||
use crate::{
|
use crate::{vertexbuffer::types::StarfieldInstance, RenderState};
|
||||||
datastructs::RenderState,
|
|
||||||
vertexbuffer::{types::StarfieldInstance, BufferObject},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) struct StarfieldStar {
|
pub(crate) struct StarfieldStar {
|
||||||
/// Star coordinates, in world space.
|
/// Star coordinates, in world space.
|
||||||
|
@ -23,15 +20,11 @@ pub(crate) struct StarfieldStar {
|
||||||
|
|
||||||
pub(crate) struct Starfield {
|
pub(crate) struct Starfield {
|
||||||
stars: Vec<StarfieldStar>,
|
stars: Vec<StarfieldStar>,
|
||||||
pub instance_count: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Starfield {
|
impl Starfield {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self { stars: Vec::new() }
|
||||||
stars: Vec::new(),
|
|
||||||
instance_count: 0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn regenerate(&mut self, ct: &Content) {
|
pub fn regenerate(&mut self, ct: &Content) {
|
||||||
|
@ -97,24 +90,19 @@ impl Starfield {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all tiles to buffer
|
// Add all tiles to buffer
|
||||||
self.instance_count = 0; // Keep track of buffer index
|
state.reset_starfield_counter();
|
||||||
for x in (-nw_tile.x)..=nw_tile.x {
|
for x in (-nw_tile.x)..=nw_tile.x {
|
||||||
for y in (-nw_tile.y)..=nw_tile.y {
|
for y in (-nw_tile.y)..=nw_tile.y {
|
||||||
let offset = Vector3::new(sz * x as f32, sz * y as f32, 0.0);
|
let offset = Vector3::new(sz * x as f32, sz * y as f32, 0.0);
|
||||||
for s in &self.stars {
|
for s in &self.stars {
|
||||||
state.queue.write_buffer(
|
// This shouldn't ever panic.
|
||||||
&state.vertex_buffers.starfield.instances,
|
// instance count is guaranteed to stay within buffer limits,
|
||||||
StarfieldInstance::SIZE * self.instance_count as u64,
|
// this is guaranteed by previous checks.
|
||||||
bytemuck::cast_slice(&[StarfieldInstance {
|
state.push_starfield_buffer(StarfieldInstance {
|
||||||
position: (s.pos + offset).into(),
|
position: (s.pos + offset).into(),
|
||||||
size: s.size,
|
size: s.size,
|
||||||
tint: s.tint.into(),
|
tint: s.tint.into(),
|
||||||
}]),
|
});
|
||||||
);
|
|
||||||
self.instance_count += 1;
|
|
||||||
|
|
||||||
// instance_count is guaranteed to stay within buffer limits,
|
|
||||||
// this is guaranteed by previous checks.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use glyphon::{Attrs, Buffer, Color, Family, Metrics, Shaping, TextArea, TextBounds};
|
use glyphon::{Attrs, Buffer, Color, Family, Metrics, Shaping, TextArea, TextBounds};
|
||||||
|
|
||||||
use crate::{datastructs::RenderState, RenderInput};
|
use crate::{RenderInput, RenderState};
|
||||||
|
|
||||||
pub(super) struct FpsIndicator {
|
pub(super) struct FpsIndicator {
|
||||||
buffer: Buffer,
|
buffer: Buffer,
|
||||||
|
|
Loading…
Reference in New Issue