diff options
Diffstat (limited to 'client/src/renderer.rs')
-rw-r--r-- | client/src/renderer.rs | 184 |
1 files changed, 166 insertions, 18 deletions
diff --git a/client/src/renderer.rs b/client/src/renderer.rs index c8f7f0b..b213307 100644 --- a/client/src/renderer.rs +++ b/client/src/renderer.rs @@ -1,22 +1,44 @@ -use std::sync::Arc; - +use crate::skin_manager::{SkinManager, init_sprite_textures}; use anyhow::{Result, anyhow}; +use log::warn; use pollster::FutureExt; +use std::{sync::Arc, time::Instant}; use twgpu::{ - Camera, GpuCamera, - map::{GpuMapData, GpuMapStatic}, - shared::Rng, - sprites::{ParticleData, SpriteTextures, SpritesData, SpritesStatic}, + Camera, GpuCamera, TwRenderPass, + blit::Blit, + buffer::GpuBuffer, + map::{GpuMapData, GpuMapRender, GpuMapStatic}, + sprites::{ParticleData, ParticleGroup, SpriteTextures, SpritesData, SpritesStatic}, textures::Samplers, }; +use twmap::TwMap; +use vek::Vec2; use wgpu::{ - Backends, DeviceDescriptor, Features, Instance, InstanceDescriptor, Limits, MemoryHints, - PowerPreference, RequestAdapterOptions, TextureFormat, + Backends, Color, CommandEncoderDescriptor, Device, DeviceDescriptor, Features, Instance, + InstanceDescriptor, Limits, LoadOp, MaintainBase, MemoryHints, Operations, PowerPreference, + Queue, RenderPassColorAttachment, RenderPassDescriptor, RequestAdapterOptions, StoreOp, + Surface, SurfaceConfiguration, TextureFormat, TextureViewDescriptor, }; -use winit::window::Window; +use winit::{dpi::PhysicalSize, window::Window}; pub struct Renderer<'a> { + device: Arc<Device>, + queue: Arc<Queue>, window: &'a Window, + surface: Surface<'a>, + surface_configuration: SurfaceConfiguration, + twmap: TwMap, + map_render: GpuMapRender, + map_data: GpuMapData, + camera: Camera, + sprites_data: SpritesData, + particle_data: ParticleData, + skin_manager: SkinManager, + sprites_static: SpritesStatic, + sprite_textures: SpriteTextures, + gpu_camera: Arc<GpuBuffer<Camera>>, + start: Instant, + need_reconfigure: bool, } impl<'a> Renderer<'a> { @@ -51,9 +73,17 @@ impl<'a> Renderer<'a> { None, ) .block_on()?; + let device = Arc::new(device); + let queue = Arc::new(queue); + + let mut twmap = TwMap::parse(include_bytes!( + "/home/muffin/etc/ddnet-maps/types/novice/maps/Mint.map" + ))?; + + twmap.load()?; let samplers = Arc::new(Samplers::new(&device)); - let mut camera = Camera::new(1.); + let camera = Camera::new(1.); let gpu_camera = Arc::new(GpuCamera::upload(&camera, &device)); let map_static = GpuMapStatic::new(texture_format, &device); @@ -62,15 +92,133 @@ impl<'a> Renderer<'a> { map_static.prepare_render(&twmap, &map_data, &gpu_camera, &samplers, &device); let sprites_static = SpritesStatic::new(texture_format, &device); - let mut sprites_data = SpritesData::new(&device); - let mut particle_data = ParticleData::new(demo.current_time(), &device); - let mut textures = SpriteTextures::new(&device, &queue, &gpu_camera, &samplers); - let mut rng = Rng::new(0); - init_sprite_textures(&mut textures, twmap.version, &device, &queue)?; + let sprites_data = SpritesData::new(&device); + let particle_data = ParticleData::new(0.0, &device); + let mut sprite_textures = SpriteTextures::new(&device, &queue, &gpu_camera, &samplers); + init_sprite_textures(&mut sprite_textures, twmap.version, &device, &queue)?; let blit = Arc::new(Blit::new(&device)); - let mut skin_manager = SkinManager::new(blit, &mut textures, device.clone(), queue.clone()); + let skin_manager = + SkinManager::new(blit, &mut sprite_textures, device.clone(), queue.clone()); + + let surface_configuration = surface + .get_default_config(&adapter, 256, 256) + .ok_or(anyhow!("no surface config"))?; + + surface.configure(&device, &surface_configuration); + + Ok(Self { + start: Instant::now(), + map_data, + sprites_static, + window, + device, + queue, + twmap, + surface, + surface_configuration, + map_render, + camera, + gpu_camera, + particle_data, + skin_manager, + sprites_data, + sprite_textures, + need_reconfigure: false, + }) + } + pub fn resize(&mut self, size: PhysicalSize<u32>) { + self.surface_configuration.width = size.width; + self.surface_configuration.height = size.height; + self.camera + .switch_aspect_ratio(size.width as f32 / size.height as f32); + self.reconfigure(); + } + pub fn reconfigure(&mut self) { + self.surface + .configure(&self.device, &self.surface_configuration); + self.need_reconfigure = false; + } + + pub fn redraw(&mut self) -> Result<()> { + if self.need_reconfigure { + self.reconfigure(); + } + let target = self.surface.get_current_texture()?; + if target.suboptimal { + warn!("suboptimal surface, need reconfigure"); + self.need_reconfigure = true; + } + + let time = self.start.elapsed().as_micros() as i64; + let size = Vec2::new( + self.surface_configuration.width, + self.surface_configuration.height, + ); + self.map_data + .update(&self.twmap, &self.camera, size, time, time, &self.queue); + self.gpu_camera.update(&self.camera, &self.queue); + + let target_view = target + .texture + .create_view(&TextureViewDescriptor::default()); + + let mut commands = self + .device + .create_command_encoder(&CommandEncoderDescriptor { label: None }); + + { + let rpass = commands.begin_render_pass(&RenderPassDescriptor { + label: None, + color_attachments: &[Some(RenderPassColorAttachment { + view: &target_view, + resolve_target: None, + ops: Operations { + load: LoadOp::Clear(Color::BLACK), + store: StoreOp::Store, + }, + })], + ..Default::default() + }); + let mut rpass = TwRenderPass::new(rpass, size, &self.camera); + self.map_render.render_background(&mut rpass); + self.sprites_static.render_particles( + &self.particle_data, + ParticleGroup::Trails, + &self.sprite_textures, + &mut rpass.render_pass, + ); + self.sprites_static.render( + &self.sprites_data, + &self.sprite_textures, + &mut rpass.render_pass, + ); + self.map_render.render_foreground(&mut rpass); + self.sprites_static.render_particles( + &self.particle_data, + ParticleGroup::Explosions, + &self.sprite_textures, + &mut rpass.render_pass, + ); + self.sprites_static.render_particles( + &self.particle_data, + ParticleGroup::Extra, + &self.sprite_textures, + &mut rpass.render_pass, + ); + self.sprites_static.render_particles( + &self.particle_data, + ParticleGroup::General, + &self.sprite_textures, + &mut rpass.render_pass, + ); + } + + let submission = self.queue.submit(Some(commands.finish())); + self.device + .poll(MaintainBase::WaitForSubmissionIndex(submission)); + + target.present(); - Self { window } + Ok(()) } - pub fn redraw() {} } |