summaryrefslogtreecommitdiff
path: root/src/renderer/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/mod.rs')
-rw-r--r--src/renderer/mod.rs871
1 files changed, 43 insertions, 828 deletions
diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs
index 2deb278..3cf340d 100644
--- a/src/renderer/mod.rs
+++ b/src/renderer/mod.rs
@@ -1,65 +1,26 @@
+mod debug;
+mod instances;
+mod particles;
mod ui;
+mod vfx;
use std::sync::Arc;
-use fxhash::FxHashMap;
use winit::window::Window;
use crate::{
Config, Diagnostics, InputManager,
camera::Camera,
- config::{CELLS_IN_CHUNK, CHUNK_SIZE},
- content::{materials::MaterialId, vfx::VfxMaterialId},
+ content::materials::MaterialId,
proc_gen::TilesetWorldGenerator,
- renderer::ui::draw_egui,
- sim::{
- cell_manager::manager::CellManager, entity::EntityId,
- rb_manager::debug_render::DebugVertex, sim_manager::SimManager,
+ renderer::{
+ debug::PhysicsDebugRendererState, instances::InstancesRendererState,
+ particles::ParticlesRendererState, ui::draw_egui, vfx::VfxRendererState,
},
+ sim::sim_manager::SimManager,
vfx::VfxManager,
};
-// TODO derive from shared chunk config
-const CHUNK_SLOTS: usize = 11 * 200;
-
-#[repr(C)]
-#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
-struct RendererInstance {
- centre: [f32; 2],
- cos_sin: [f32; 2],
- half_size: [f32; 2],
- dims: [u32; 2],
- cell_offset: u32,
- _padding: u32,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
-struct RendererParticle {
- position: [f32; 2],
- data: u32,
- life: f32,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
-struct RendererVfxMaterial {
- color: [f32; 4],
- length: f32,
- _padding: [u32; 3],
-}
-
-#[repr(C)]
-#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
-struct RendererVfxLine {
- a: [f32; 2],
- b: [f32; 2],
- width: f32,
- material: u32,
- alive_for: f32,
- lifetime: f32,
-}
-
fn srgb_to_linear(channel: u8) -> f32 {
let channel = channel as f32 / 255.0;
if channel <= 0.04045 {
@@ -69,54 +30,6 @@ fn srgb_to_linear(channel: u8) -> f32 {
}
}
-const DEBUG_VERTEX_ATTRIBUTES: [wgpu::VertexAttribute; 2] =
- wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x4];
-
-fn create_debug_vertex_buffer(device: &wgpu::Device, capacity: usize) -> wgpu::Buffer {
- device.create_buffer(&wgpu::BufferDescriptor {
- label: Some("Debug vertex buffer"),
- size: (capacity * size_of::<DebugVertex>()) as u64,
- usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
- mapped_at_creation: false,
- })
-}
-
-fn create_instance_buffer(device: &wgpu::Device, capacity: usize) -> wgpu::Buffer {
- device.create_buffer(&wgpu::BufferDescriptor {
- label: Some("Instance buffer"),
- size: (capacity * size_of::<RendererInstance>()) as u64,
- usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
- mapped_at_creation: false,
- })
-}
-
-fn create_cell_buffer(device: &wgpu::Device, capacity: usize) -> wgpu::Buffer {
- device.create_buffer(&wgpu::BufferDescriptor {
- label: Some("Cell buffer"),
- size: (capacity * CELLS_IN_CHUNK) as u64,
- usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
- mapped_at_creation: false,
- })
-}
-
-fn create_particle_buffer(device: &wgpu::Device, capacity: usize) -> wgpu::Buffer {
- device.create_buffer(&wgpu::BufferDescriptor {
- label: Some("Particle buffer"),
- size: (capacity * size_of::<RendererParticle>()) as u64,
- usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
- mapped_at_creation: false,
- })
-}
-
-fn create_vfx_line_buffer(device: &wgpu::Device, capacity: usize) -> wgpu::Buffer {
- device.create_buffer(&wgpu::BufferDescriptor {
- label: Some("VFX line buffer"),
- size: (capacity * size_of::<RendererVfxLine>()) as u64,
- usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
- mapped_at_creation: false,
- })
-}
-
pub struct RendererState {
window: Arc<Window>,
surface: wgpu::Surface<'static>,
@@ -134,36 +47,13 @@ pub struct RendererState {
// common
camera_uniform_buffer: wgpu::Buffer,
- // instances
- instance_pipeline: wgpu::RenderPipeline,
- instance_buffer: wgpu::Buffer,
- cell_buffer: wgpu::Buffer,
- instance_bind_group: wgpu::BindGroup,
- entity_capacity: usize,
-
- // particles
- particle_pipeline: wgpu::RenderPipeline,
- particle_buffer: wgpu::Buffer,
- particle_bind_group: wgpu::BindGroup,
- particle_capacity: usize,
-
- // vfx
- vfx_line_pipeline: wgpu::RenderPipeline,
- vfx_line_buffer: wgpu::Buffer,
- vfx_line_bind_group: wgpu::BindGroup,
- vfx_line_capacity: usize,
-
- // physics debug lines
- debug_pipeline: wgpu::RenderPipeline,
- debug_bind_group: wgpu::BindGroup,
- debug_vertex_buffer: wgpu::Buffer,
- debug_vertex_capacity: usize,
-
- renderer_rb_entities: FxHashMap<EntityId, usize>,
+ instances_renderer_state: InstancesRendererState,
+ particles_renderer_state: ParticlesRendererState,
+ vfx_renderer_state: VfxRendererState,
+ physics_debug_renderer_state: PhysicsDebugRendererState,
}
impl RendererState {
- // https://sotrh.github.io/learn-wgpu/beginner/tutorial1-window
pub async fn new(window: Arc<Window>) -> Self {
let size = window.inner_size();
println!("Got window! ({}x{})", size.width, size.height);
@@ -253,135 +143,6 @@ impl RendererState {
queue.write_buffer(&palette_buffer, 0, bytemuck::cast_slice(&palette));
- // --- VFX materials ---
- let mut vfx_material_palette = [RendererVfxMaterial {
- color: [0.0f32; 4],
- length: 0.0,
- _padding: [0; 3],
- }; VfxMaterialId::ALL.len()];
- for material in VfxMaterialId::ALL {
- let def = material.def();
- let i = material as usize;
- vfx_material_palette[i].color = [
- srgb_to_linear(def.color.0),
- srgb_to_linear(def.color.1),
- srgb_to_linear(def.color.2),
- def.color.3 as f32 / 255.0,
- ];
- vfx_material_palette[i].length = def.length;
- }
-
- let vfx_material_palette_buffer = device.create_buffer(&wgpu::BufferDescriptor {
- label: Some("VFX Material Palette buffer"),
- size: size_of_val(&vfx_material_palette) as u64,
- usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
- mapped_at_creation: false,
- });
-
- queue.write_buffer(
- &vfx_material_palette_buffer,
- 0,
- bytemuck::cast_slice(&vfx_material_palette),
- );
-
- // --- INSTANCES ---
- let instance_bind_group_layout =
- device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
- label: None,
- entries: &[
- // camera uniform
- wgpu::BindGroupLayoutEntry {
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Uniform,
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- binding: 0,
- count: None,
- visibility: wgpu::ShaderStages::VERTEX,
- },
- // palette
- wgpu::BindGroupLayoutEntry {
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Storage { read_only: true },
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- binding: 1,
- count: None,
- visibility: wgpu::ShaderStages::FRAGMENT,
- },
- // instance buffer
- wgpu::BindGroupLayoutEntry {
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Storage { read_only: true },
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- binding: 2,
- count: None,
- visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
- },
- // cells
- wgpu::BindGroupLayoutEntry {
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Storage { read_only: true },
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- binding: 3,
- count: None,
- visibility: wgpu::ShaderStages::FRAGMENT,
- },
- ],
- });
-
- let instance_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
- label: Some("Instance shader"),
- source: wgpu::ShaderSource::Wgsl(include_str!("../shader/instance.wgsl").into()),
- });
-
- let instance_pipeline_layout =
- device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
- label: None,
- immediate_size: 0,
- bind_group_layouts: &[Some(&instance_bind_group_layout)],
- });
-
- let instance_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
- label: None,
- layout: Some(&instance_pipeline_layout),
- vertex: wgpu::VertexState {
- module: &instance_shader,
- entry_point: Some("vs_main"),
- buffers: &[],
- compilation_options: wgpu::PipelineCompilationOptions::default(),
- },
- fragment: Some(wgpu::FragmentState {
- module: &instance_shader,
- entry_point: Some("fs_main"),
- targets: &[Some(wgpu::ColorTargetState {
- format: config.format,
- blend: Some(wgpu::BlendState::ALPHA_BLENDING),
- write_mask: wgpu::ColorWrites::ALL,
- })],
- compilation_options: wgpu::PipelineCompilationOptions::default(),
- }),
- primitive: wgpu::PrimitiveState {
- topology: wgpu::PrimitiveTopology::TriangleStrip,
- strip_index_format: None,
- front_face: wgpu::FrontFace::Ccw,
- cull_mode: None,
- polygon_mode: wgpu::PolygonMode::Fill,
- unclipped_depth: false,
- conservative: false,
- },
- depth_stencil: None,
- multisample: wgpu::MultisampleState::default(),
- multiview_mask: None,
- cache: None,
- });
-
let camera_uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("Camera uniform buffer"),
size: 16,
@@ -389,333 +150,17 @@ impl RendererState {
mapped_at_creation: false,
});
- let entity_capacity = 2048;
- let instance_buffer = create_instance_buffer(&device, CHUNK_SLOTS + entity_capacity);
-
- let cell_buffer = create_cell_buffer(&device, entity_capacity + CHUNK_SLOTS);
-
- let instance_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
- label: None,
- layout: &instance_bind_group_layout,
- entries: &[
- wgpu::BindGroupEntry {
- binding: 0,
- resource: camera_uniform_buffer.as_entire_binding(),
- },
- wgpu::BindGroupEntry {
- binding: 1,
- resource: palette_buffer.as_entire_binding(),
- },
- wgpu::BindGroupEntry {
- binding: 2,
- resource: instance_buffer.as_entire_binding(),
- },
- wgpu::BindGroupEntry {
- binding: 3,
- resource: cell_buffer.as_entire_binding(),
- },
- ],
- });
-
- // --- PARTICLES ---
- let particle_bind_group_layout =
- device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
- label: None,
- entries: &[
- // camera uniform
- wgpu::BindGroupLayoutEntry {
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Uniform,
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- binding: 0,
- count: None,
- visibility: wgpu::ShaderStages::VERTEX,
- },
- // palette
- wgpu::BindGroupLayoutEntry {
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Storage { read_only: true },
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- binding: 1,
- count: None,
- visibility: wgpu::ShaderStages::FRAGMENT,
- },
- // instance buffer
- wgpu::BindGroupLayoutEntry {
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Storage { read_only: true },
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- binding: 2,
- count: None,
- visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
- },
- ],
- });
-
- let particle_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
- label: Some("Particle shader"),
- source: wgpu::ShaderSource::Wgsl(include_str!("../shader/particle.wgsl").into()),
- });
-
- let particle_pipeline_layout =
- device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
- label: None,
- immediate_size: 0,
- bind_group_layouts: &[Some(&particle_bind_group_layout)],
- });
-
- let particle_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
- label: None,
- layout: Some(&particle_pipeline_layout),
- vertex: wgpu::VertexState {
- module: &particle_shader,
- entry_point: Some("vs_main"),
- buffers: &[],
- compilation_options: wgpu::PipelineCompilationOptions::default(),
- },
- fragment: Some(wgpu::FragmentState {
- module: &particle_shader,
- entry_point: Some("fs_main"),
- targets: &[Some(wgpu::ColorTargetState {
- format: config.format,
- blend: Some(wgpu::BlendState::ALPHA_BLENDING),
- write_mask: wgpu::ColorWrites::ALL,
- })],
- compilation_options: wgpu::PipelineCompilationOptions::default(),
- }),
- primitive: wgpu::PrimitiveState {
- topology: wgpu::PrimitiveTopology::TriangleStrip,
- strip_index_format: None,
- front_face: wgpu::FrontFace::Ccw,
- cull_mode: None,
- polygon_mode: wgpu::PolygonMode::Fill,
- unclipped_depth: false,
- conservative: false,
- },
- depth_stencil: None,
- multisample: wgpu::MultisampleState::default(),
- multiview_mask: None,
- cache: None,
- });
-
- let particle_capacity = 2048;
- let particle_buffer = create_particle_buffer(&device, particle_capacity);
-
- let particle_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
- label: None,
- layout: &particle_bind_group_layout,
- entries: &[
- wgpu::BindGroupEntry {
- binding: 0,
- resource: camera_uniform_buffer.as_entire_binding(),
- },
- wgpu::BindGroupEntry {
- binding: 1,
- resource: palette_buffer.as_entire_binding(),
- },
- wgpu::BindGroupEntry {
- binding: 2,
- resource: particle_buffer.as_entire_binding(),
- },
- ],
- });
-
- // --- VFX_LINES ---
- let vfx_line_bind_group_layout =
- device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
- label: None,
- entries: &[
- // camera uniform
- wgpu::BindGroupLayoutEntry {
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Uniform,
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- binding: 0,
- count: None,
- visibility: wgpu::ShaderStages::VERTEX,
- },
- // material palette
- wgpu::BindGroupLayoutEntry {
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Storage { read_only: true },
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- binding: 1,
- count: None,
- // don't need vertex here
- visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
- },
- // instance buffer
- wgpu::BindGroupLayoutEntry {
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Storage { read_only: true },
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- binding: 2,
- count: None,
- visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
- },
- ],
- });
-
- let vfx_line_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
- label: Some("VFX Line shader"),
- source: wgpu::ShaderSource::Wgsl(include_str!("../shader/vfx_line.wgsl").into()),
- });
+ let instances_renderer_state =
+ InstancesRendererState::new(&device, &config, &camera_uniform_buffer, &palette_buffer);
- let vfx_line_pipeline_layout =
- device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
- label: None,
- immediate_size: 0,
- bind_group_layouts: &[Some(&vfx_line_bind_group_layout)],
- });
+ let particles_renderer_state =
+ ParticlesRendererState::new(&device, &config, &camera_uniform_buffer, &palette_buffer);
- let vfx_line_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
- label: None,
- layout: Some(&vfx_line_pipeline_layout),
- vertex: wgpu::VertexState {
- module: &vfx_line_shader,
- entry_point: Some("vs_main"),
- buffers: &[],
- compilation_options: wgpu::PipelineCompilationOptions::default(),
- },
- fragment: Some(wgpu::FragmentState {
- module: &vfx_line_shader,
- entry_point: Some("fs_main"),
- targets: &[Some(wgpu::ColorTargetState {
- format: config.format,
- blend: Some(wgpu::BlendState::ALPHA_BLENDING),
- write_mask: wgpu::ColorWrites::ALL,
- })],
- compilation_options: wgpu::PipelineCompilationOptions::default(),
- }),
- primitive: wgpu::PrimitiveState {
- topology: wgpu::PrimitiveTopology::TriangleStrip,
- strip_index_format: None,
- front_face: wgpu::FrontFace::Ccw,
- cull_mode: None,
- polygon_mode: wgpu::PolygonMode::Fill,
- unclipped_depth: false,
- conservative: false,
- },
- depth_stencil: None,
- multisample: wgpu::MultisampleState::default(),
- multiview_mask: None,
- cache: None,
- });
+ let vfx_renderer_state =
+ VfxRendererState::new(&device, &queue, &config, &camera_uniform_buffer);
- let vfx_line_capacity = 512;
- let vfx_line_buffer = create_vfx_line_buffer(&device, vfx_line_capacity);
-
- let vfx_line_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
- label: None,
- layout: &vfx_line_bind_group_layout,
- entries: &[
- wgpu::BindGroupEntry {
- binding: 0,
- resource: camera_uniform_buffer.as_entire_binding(),
- },
- wgpu::BindGroupEntry {
- binding: 1,
- resource: vfx_material_palette_buffer.as_entire_binding(),
- },
- wgpu::BindGroupEntry {
- binding: 2,
- resource: vfx_line_buffer.as_entire_binding(),
- },
- ],
- });
-
- // --- DEBUG ---
- let debug_bind_group_layout =
- device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
- label: Some("Debug bind group layout"),
- entries: &[
- // camera uniform
- wgpu::BindGroupLayoutEntry {
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Uniform,
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- binding: 0,
- count: None,
- visibility: wgpu::ShaderStages::VERTEX,
- },
- ],
- });
-
- let debug_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
- label: Some("Debug bind group"),
- layout: &debug_bind_group_layout,
- entries: &[wgpu::BindGroupEntry {
- binding: 0,
- resource: camera_uniform_buffer.as_entire_binding(),
- }],
- });
-
- let debug_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
- label: Some("Debug shader"),
- source: wgpu::ShaderSource::Wgsl(include_str!("../shader/debug.wgsl").into()),
- });
-
- let debug_pipeline_layout =
- device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
- label: Some("Debug pipeline layout"),
- immediate_size: 0,
- bind_group_layouts: &[Some(&debug_bind_group_layout)],
- });
-
- let debug_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
- label: Some("Debug pipeline"),
- layout: Some(&debug_pipeline_layout),
- vertex: wgpu::VertexState {
- module: &debug_shader,
- entry_point: Some("vs_main"),
- buffers: &[wgpu::VertexBufferLayout {
- array_stride: size_of::<DebugVertex>() as wgpu::BufferAddress,
- step_mode: wgpu::VertexStepMode::Vertex,
- attributes: &DEBUG_VERTEX_ATTRIBUTES,
- }],
- compilation_options: wgpu::PipelineCompilationOptions::default(),
- },
- fragment: Some(wgpu::FragmentState {
- module: &debug_shader,
- entry_point: Some("fs_main"),
- targets: &[Some(wgpu::ColorTargetState {
- format: config.format,
- blend: Some(wgpu::BlendState::ALPHA_BLENDING),
- write_mask: wgpu::ColorWrites::ALL,
- })],
- compilation_options: wgpu::PipelineCompilationOptions::default(),
- }),
- primitive: wgpu::PrimitiveState {
- topology: wgpu::PrimitiveTopology::LineList,
- strip_index_format: None,
- front_face: wgpu::FrontFace::Ccw,
- cull_mode: None,
- polygon_mode: wgpu::PolygonMode::Fill,
- unclipped_depth: false,
- conservative: false,
- },
- depth_stencil: None,
- multisample: wgpu::MultisampleState::default(),
- multiview_mask: None,
- cache: None,
- });
-
- let debug_vertex_capacity = 4096;
- let debug_vertex_buffer = create_debug_vertex_buffer(&device, debug_vertex_capacity);
+ let physics_debug_renderer_state =
+ PhysicsDebugRendererState::new(&device, &config, &camera_uniform_buffer);
RendererState {
window,
@@ -731,28 +176,10 @@ impl RendererState {
camera_uniform_buffer,
- instance_pipeline,
- instance_buffer,
- cell_buffer,
- instance_bind_group,
- entity_capacity,
-
- particle_pipeline,
- particle_buffer,
- particle_bind_group,
- particle_capacity,
-
- vfx_line_pipeline,
- vfx_line_buffer,
- vfx_line_bind_group,
- vfx_line_capacity,
-
- debug_pipeline,
- debug_bind_group,
- debug_vertex_buffer,
- debug_vertex_capacity,
-
- renderer_rb_entities: FxHashMap::default(),
+ instances_renderer_state,
+ particles_renderer_state,
+ vfx_renderer_state,
+ physics_debug_renderer_state,
}
}
@@ -868,207 +295,21 @@ impl RendererState {
bytemuck::bytes_of(&camera.to_uniform()),
);
- let mut cell_buffer: [u8; CELLS_IN_CHUNK] = [0; CELLS_IN_CHUNK];
- let mut instances: Vec<RendererInstance> = Vec::new();
-
- {
- puffin::profile_scope!("Upload chunk cells");
- for &idx in sim.cell_manager.chunk_position_to_chunk_idx.values() {
- let chunk = &mut sim.cell_manager.chunks[idx];
- if !chunk.needs_texture_update {
- continue;
- }
- chunk.needs_texture_update = false;
-
- for (byte, cell) in cell_buffer.iter_mut().zip(chunk.cells.iter()) {
- *byte = cell.material as u8;
- }
-
- self.queue.write_buffer(
- &self.cell_buffer,
- (idx * CELLS_IN_CHUNK) as u64,
- &cell_buffer,
- );
- }
- }
-
- {
- puffin::profile_scope!("Upload entity cells");
- // TODO optimize, this is very inefficient, just build it per frame with positions and skip the lookup?
- self.renderer_rb_entities.clear();
- for entity in sim.entities.values() {
- // TODO add "needs texture update"?
- if let Some(cells) = &entity.data.cells {
- for i in 0..cells.cells.len() {
- cell_buffer[i] = cells.cells[i].material as u8;
- }
-
- let next_slot = CHUNK_SLOTS + self.renderer_rb_entities.len();
- let slot = *self
- .renderer_rb_entities
- .entry(entity.data.id)
- .or_insert(next_slot);
-
- self.queue.write_buffer(
- &self.cell_buffer,
- (slot * CHUNK_SIZE as usize * CHUNK_SIZE as usize) as u64,
- &cell_buffer,
- );
- }
- }
- }
-
- {
- puffin::profile_scope!("Build instances");
- let (lower, upper) = camera.viewport_bounds_world();
- let ((cxl, cyl), _) =
- CellManager::split_game_position(lower.x.floor() as i32, lower.y.floor() as i32);
- let ((cxu, cyu), _) =
- CellManager::split_game_position(upper.x.floor() as i32, upper.y.floor() as i32);
-
- let half_size = [CHUNK_SIZE as f32 / 2.0, CHUNK_SIZE as f32 / 2.0];
- let dims = [CHUNK_SIZE as u32, CHUNK_SIZE as u32];
-
- for cx in cxl..=cxu {
- for cy in cyl..=cyu {
- if let Some(idx) = sim.cell_manager.chunk_position_to_chunk_idx.get(&(cx, cy)) {
- instances.push(RendererInstance {
- centre: [
- (cx * CHUNK_SIZE) as f32 + half_size[0],
- (cy * CHUNK_SIZE) as f32 + half_size[1],
- ],
- cos_sin: [1.0, 0.0],
- half_size,
- dims,
- cell_offset: (idx * CELLS_IN_CHUNK) as u32,
- _padding: 0,
- });
- }
- }
- }
-
- let mut entities = 0;
- for (id, slot) in &self.renderer_rb_entities {
- if let Some(entity) = sim.entities.get(id)
- && let Some(cells) = &entity.data.cells
- && let Some((pos, (cos, sin))) = entity.data._transform(&sim.rb_manager)
- {
- // TODO access this better
- // let sleeping = sim
- // .rb_manager
- // .physics_manager
- // .world
- // .bodies
- // .get(entity.data.rb_h.unwrap())
- // .unwrap()
- // .is_sleeping();
- let sleeping = false;
-
- entities += 1;
- instances.push(RendererInstance {
- centre: if sleeping {
- pos.round().to_array()
- } else {
- pos.to_array()
- },
- cos_sin: [cos, sin],
- half_size: (cells.size / 2).as_vec2().to_array(),
- dims: cells.size.as_uvec2().to_array(),
- cell_offset: (slot * CHUNK_SIZE as usize * CHUNK_SIZE as usize) as u32,
- _padding: 0,
- });
- }
- }
-
- if entities > self.entity_capacity {
- self.entity_capacity = entities.next_power_of_two();
- self.instance_buffer =
- create_instance_buffer(&self.device, self.entity_capacity + CHUNK_SLOTS);
- self.cell_buffer =
- create_cell_buffer(&self.device, CHUNK_SLOTS + self.entity_capacity);
- }
-
- self.queue
- .write_buffer(&self.instance_buffer, 0, bytemuck::cast_slice(&instances));
- }
-
- let mut particles: Vec<RendererParticle> = Vec::new();
-
- {
- puffin::profile_scope!("Build particles");
- // TODO could cull this to visible, maybe it's slower?
- particles = sim
- .particle_manager
- .particles
- .iter()
- .map(|p| RendererParticle {
- position: [p.position.x, p.position.y],
- data: p.material as u32,
- life: p.life,
- })
- .collect();
-
- if particles.len() > self.particle_capacity {
- self.particle_capacity = particles.len().next_power_of_two();
- self.particle_buffer = create_particle_buffer(&self.device, self.particle_capacity);
- }
-
- self.queue
- .write_buffer(&self.particle_buffer, 0, bytemuck::cast_slice(&particles));
- }
-
- let mut vfx_lines: Vec<RendererVfxLine> = Vec::new();
-
- {
- puffin::profile_scope!("Build VFX lines");
- // TODO could cull this to visible, maybe it's slower?
- vfx_lines = vfx_manager
- .lines
- .iter()
- .map(|p| RendererVfxLine {
- a: p.a.to_array(),
- b: p.b.to_array(),
- material: p.material as u32,
- width: p.width,
- alive_for: p.alive_for,
- lifetime: p.lifetime,
- })
- .collect();
-
- if vfx_lines.len() > self.vfx_line_capacity {
- self.vfx_line_capacity = vfx_lines.len().next_power_of_two();
- self.vfx_line_buffer = create_vfx_line_buffer(&self.device, self.vfx_line_capacity);
- }
-
- self.queue
- .write_buffer(&self.vfx_line_buffer, 0, bytemuck::cast_slice(&vfx_lines));
+ self.instances_renderer_state
+ .update_buffers(&self.device, &self.queue, sim, camera);
+ self.particles_renderer_state
+ .update_buffers(&self.device, &self.queue, sim);
+ self.vfx_renderer_state
+ .update_buffers(&self.device, &self.queue, vfx_manager);
+ if config.debug_render {
+ self.physics_debug_renderer_state.update_buffers(
+ &self.device,
+ &self.queue,
+ sim,
+ config.debug_render_mode,
+ );
}
- let debug_vertex_count = if config.debug_render {
- puffin::profile_scope!("Build physics debug lines");
- let vertices = sim.rb_manager.debug_render(config.debug_render_mode);
-
- if vertices.is_empty() {
- 0
- } else {
- if vertices.len() > self.debug_vertex_capacity {
- self.debug_vertex_capacity = vertices.len().next_power_of_two();
- self.debug_vertex_buffer =
- create_debug_vertex_buffer(&self.device, self.debug_vertex_capacity);
- }
-
- self.queue.write_buffer(
- &self.debug_vertex_buffer,
- 0,
- bytemuck::cast_slice(vertices),
- );
-
- vertices.len() as u32
- }
- } else {
- 0
- };
-
{
puffin::profile_scope!("Main render pass");
let mut render_pass: wgpu::RenderPass<'_> =
@@ -1094,37 +335,11 @@ impl RendererState {
multiview_mask: None,
});
- // this is kind of a hack
- let instances_start = u32::min(
- if config.cells_render {
- 0
- } else {
- CHUNK_SLOTS as u32
- },
- instances.len() as u32 - 1,
- );
-
- // instances
- render_pass.set_pipeline(&self.instance_pipeline);
- render_pass.set_bind_group(0, &self.instance_bind_group, &[]);
- render_pass.draw(0..4, instances_start..instances.len() as u32);
-
- // particles
- render_pass.set_pipeline(&self.particle_pipeline);
- render_pass.set_bind_group(0, &self.particle_bind_group, &[]);
- render_pass.draw(0..4, 0..particles.len() as u32);
-
- // vfx
- render_pass.set_pipeline(&self.vfx_line_pipeline);
- render_pass.set_bind_group(0, &self.vfx_line_bind_group, &[]);
- render_pass.draw(0..4, 0..vfx_lines.len() as u32);
-
- // debug
- if debug_vertex_count > 0 {
- render_pass.set_pipeline(&self.debug_pipeline);
- render_pass.set_bind_group(0, &self.debug_bind_group, &[]);
- render_pass.set_vertex_buffer(0, self.debug_vertex_buffer.slice(..));
- render_pass.draw(0..debug_vertex_count, 0..1);
+ self.instances_renderer_state.render(&mut render_pass);
+ self.particles_renderer_state.render(&mut render_pass);
+ self.vfx_renderer_state.render(&mut render_pass);
+ if config.debug_render {
+ self.physics_debug_renderer_state.render(&mut render_pass);
}
}