Changed to one dynamic model per entity.

This commit is contained in:
Sam 2022-01-25 15:49:06 -05:00
parent d9028ec978
commit 05f53a5316
4 changed files with 14 additions and 148 deletions

View File

@ -36,7 +36,7 @@ pub use self::{
Vertex as SpriteVertex, VERT_PAGE_SIZE as SPRITE_VERT_PAGE_SIZE,
},
terrain::{Locals as TerrainLocals, TerrainLayout, Vertex as TerrainVertex},
trail::{Instance as TrailInstance, Vertex as TrailVertex},
trail::Vertex as TrailVertex,
ui::{
create_quad as create_ui_quad,
create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri,

View File

@ -1,7 +1,6 @@
use super::super::{AaMode, GlobalsLayouts, Vertex as VertexTrait};
use bytemuck::{Pod, Zeroable};
use std::mem;
use vek::*;
#[repr(C)]
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
@ -26,49 +25,6 @@ impl VertexTrait for Vertex {
const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
pub struct Instance {
// created_at time, so we can calculate time relativity, needed for relative animation.
// can save 32 bits per instance, for trails that are not relatively animated.
inst_time: f32,
// The lifespan in seconds of the trail
inst_lifespan: f32,
// The two positions that define where the line of the object making the trail, e.g. sword tip
// and sword hilt
inner_pos: [f32; 3],
outer_pos: [f32; 3],
}
impl Instance {
pub fn new(inst_time: f64, lifespan: f32, inner_pos: Vec3<f32>, outer_pos: Vec3<f32>) -> Self {
Self {
inst_time: inst_time as f32,
inst_lifespan: lifespan,
inner_pos: inner_pos.into_array(),
outer_pos: outer_pos.into_array(),
}
}
fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
const ATTRIBUTES: [wgpu::VertexAttribute; 4] =
wgpu::vertex_attr_array![2 => Float32, 3 => Float32, 4 => Float32x3, 5 => Float32x3];
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Instance,
attributes: &ATTRIBUTES,
}
}
pub fn points(&self) -> ([f32; 3], [f32; 3]) { (self.inner_pos, self.outer_pos) }
}
impl Default for Instance {
fn default() -> Self { Self::new(0.0, 0.0, Vec3::zero(), Vec3::zero()) }
}
pub struct TrailPipeline {
pub pipeline: wgpu::RenderPipeline,
}
@ -102,7 +58,7 @@ impl TrailPipeline {
vertex: wgpu::VertexState {
module: vs_module,
entry_point: "main",
buffers: &[Vertex::desc(), Instance::desc()],
buffers: &[Vertex::desc()],
},
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,

View File

@ -877,17 +877,11 @@ pub struct TrailDrawer<'pass_ref, 'pass: 'pass_ref> {
}
impl<'pass_ref, 'pass: 'pass_ref> TrailDrawer<'pass_ref, 'pass> {
pub fn draw<'data: 'pass>(
&mut self,
model: &'data DynamicModel<trail::Vertex>,
instances: &'data Instances<trail::Instance>,
) {
pub fn draw<'data: 'pass>(&mut self, model: &'data DynamicModel<trail::Vertex>) {
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
self.render_pass
.set_vertex_buffer(0, instances.buf().slice(..));
self.render_pass
// TODO: since we cast to u32 maybe this should returned by the len/count functions?
.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..instances.count() as u32);
.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..0);
}
}

View File

@ -1,115 +1,31 @@
use super::SceneData;
use crate::render::{
DynamicModel, Instances, Mesh, Quad, Renderer, TrailDrawer, TrailInstance, TrailVertex,
};
use crate::render::{DynamicModel, Renderer, TrailDrawer, TrailVertex};
use common::uid::Uid;
use common_base::span;
use std::time::Duration;
use vek::*;
use std::collections::HashMap;
pub struct TrailMgr {
/// keep track of lifespans
trails: Vec<Trail>,
/// GPU Instance Buffer
instances: Instances<TrailInstance>,
/// GPU vertex buffers
dynamic_model: DynamicModel<TrailVertex>,
dynamic_models: HashMap<Uid, DynamicModel<TrailVertex>>,
}
impl TrailMgr {
pub fn new(renderer: &mut Renderer) -> Self {
pub fn new(_renderer: &mut Renderer) -> Self {
Self {
trails: Vec::new(),
instances: default_instances(renderer),
dynamic_model: renderer.create_dynamic_model(120),
dynamic_models: HashMap::new(),
}
}
pub fn maintain(&mut self, renderer: &mut Renderer, scene_data: &SceneData) {
pub fn maintain(&mut self, _renderer: &mut Renderer, _scene_data: &SceneData) {
span!(_guard, "maintain", "TrailMgr::maintain");
if scene_data.trails_enabled {
// remove dead Trails
self.trails
.retain(|p| p.alive_until > scene_data.state.get_time());
// add new Trails
self.upload_trails(renderer);
} else {
// remove all trail lifespans
if !self.trails.is_empty() {
self.trails.clear();
self.upload_trails(renderer);
}
}
}
fn upload_trails(&mut self, renderer: &mut Renderer) {
span!(_guard, "upload_trails", "TrailMgr::upload_trails");
let all_cpu_instances = self
.trails
.iter()
.map(|t| t.instance)
.collect::<Vec<TrailInstance>>();
// TODO: optimise buffer writes
let gpu_instances = renderer
.create_instances(&all_cpu_instances)
.expect("Failed to upload trail instances to the GPU!");
self.instances = gpu_instances;
for (i, trail) in self.trails.iter().enumerate() {
if i > 0 {
if let Some((inner1, outer1)) = self.trails.get(i - 1).map(|t| t.instance.points())
{
let (inner2, outer2) = trail.instance.points();
let point = |pos| TrailVertex { pos };
let mut mesh = Mesh::new();
mesh.push_quad(Quad::new(
point(inner1),
point(outer1),
point(inner2),
point(outer2),
));
renderer.update_model(&self.dynamic_model, &mesh, 4 * i)
}
}
}
}
pub fn render<'a>(&'a self, drawer: &mut TrailDrawer<'_, 'a>, scene_data: &SceneData) {
span!(_guard, "render", "TrailMgr::render");
if scene_data.trails_enabled {
drawer.draw(&self.dynamic_model, &self.instances);
}
}
pub fn trail_count(&self) -> usize { self.instances.count() }
pub fn trail_count_visible(&self) -> usize { self.instances.count() }
}
fn default_instances(renderer: &mut Renderer) -> Instances<TrailInstance> {
let empty_vec = Vec::new();
renderer
.create_instances(&empty_vec)
.expect("Failed to upload trail instances to the GPU!")
}
#[derive(Clone, Copy)]
struct Trail {
alive_until: f64, // created_at + lifespan
instance: TrailInstance,
}
impl Trail {
fn new(lifespan: Duration, time: f64, inner_pos: Vec3<f32>, outer_pos: Vec3<f32>) -> Self {
Trail {
alive_until: time + lifespan.as_secs_f64(),
instance: TrailInstance::new(time, lifespan.as_secs_f32(), inner_pos, outer_pos),
for dynamic_model in self.dynamic_models.values() {
drawer.draw(dynamic_model);
}
}
}
}