diff options
author | tcmal <me@aria.rip> | 2024-08-25 17:44:20 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-08-25 17:44:20 +0100 |
commit | 19b5dfb37ad45eaff18fb14e9134d1386cb696e9 (patch) | |
tree | 793d398cfbbd2426401fc62269a3c092820bef7d | |
parent | 8b42054f1521bfc020e22a4ad7d1dd0ea04e1206 (diff) |
feat(render): render bsp w/ culling stubs
-rw-r--r-- | stockton-render/src/draw/camera.rs | 30 | ||||
-rw-r--r-- | stockton-render/src/draw/context.rs | 125 | ||||
-rw-r--r-- | stockton-render/src/lib.rs | 27 |
3 files changed, 131 insertions, 51 deletions
diff --git a/stockton-render/src/draw/camera.rs b/stockton-render/src/draw/camera.rs index 6733cd7..2abf814 100644 --- a/stockton-render/src/draw/camera.rs +++ b/stockton-render/src/draw/camera.rs @@ -29,22 +29,22 @@ use stockton_types::{Vector3, Matrix4}; pub struct CameraSettings { /// Position of the camera - position: Vector3, + pub position: Vector3, /// A point the camera is looking directly at - looking_at: Vector3, + pub looking_at: Vector3, /// The up direction - up: Vector3, + pub up: Vector3, /// FOV in radians - fov: f32, + pub fov: f32, /// Near clipping plane (world units) - near: f32, + pub near: f32, /// Far clipping plane (world units) - far: f32, + pub far: f32, } /// Holds settings related to the projection of world space to screen space @@ -76,12 +76,12 @@ impl<'a> WorkingCamera<'a> { command_queue: &mut CommandQueue, command_pool: &mut CommandPool) -> Result<WorkingCamera<'a>, error::CreationError> { WorkingCamera::with_settings(CameraSettings { - position: Vector3::new(-0.5, 1.5, -1.0), - looking_at: Vector3::new(0.5, 0.5, 0.5), + position: Vector3::new(-320.0, 0.0, 0.0), + looking_at: Vector3::new(0.0, 0.0, 0.0), up: Vector3::new(0.0, 1.0, 0.0), fov: f32::to_radians(90.0), near: 0.1, - far: 100.0, + far: 1024.0, }, aspect_ratio, device, adapter, command_queue, command_pool) } @@ -202,11 +202,19 @@ impl<'a> WorkingCamera<'a> { projection_matrix * view_matrix } + /// Update the aspect ratio pub fn update_aspect_ratio(&mut self, new: f32) { self.aspect_ratio = new; self.is_dirty = true; } + /// Move the camera by `delta` + pub fn move_camera(&mut self, delta: Vector3) { + self.settings.position += delta; + self.is_dirty = true; + } + + /// Ensures the VP matrix on the GPU is up-to-date pub fn commit<'b>(&'b mut self, device: &Device, command_queue: &mut CommandQueue, command_pool: &mut CommandPool) -> &'b DescriptorSet { @@ -234,4 +242,8 @@ impl<'a> WorkingCamera<'a> { device.destroy_descriptor_set_layout(ManuallyDrop::into_inner(read(&self.descriptor_set_layout))); } } + + pub fn camera_pos(&self) -> Vector3 { + self.settings.position + } }
\ No newline at end of file diff --git a/stockton-render/src/draw/context.rs b/stockton-render/src/draw/context.rs index d9d426d..12f24ad 100644 --- a/stockton-render/src/draw/context.rs +++ b/stockton-render/src/draw/context.rs @@ -20,7 +20,8 @@ use std::{ mem::{ManuallyDrop, size_of}, ops::Deref, - borrow::Borrow + borrow::Borrow, + convert::TryInto }; use winit::window::Window; use arrayvec::ArrayVec; @@ -32,12 +33,20 @@ use hal::{ window::SwapchainConfig }; use stockton_types::{Vector2, Vector3}; +use stockton_bsp::{ + BSPFile, + lumps::faces::FaceType +}; -use crate::types::*; -use crate::error; -use super::camera::WorkingCamera; -use super::texture::TextureStore; -use super::buffer::{StagedBuffer, ModifiableBuffer}; +use crate::{ + types::*, + error +}; +use super::{ + camera::WorkingCamera, + texture::TextureStore, + buffer::{StagedBuffer, ModifiableBuffer} +}; /// Entry point name for shaders const ENTRY_NAME: &str = "main"; @@ -53,10 +62,10 @@ const COLOR_RANGE: hal::image::SubresourceRange = hal::image::SubresourceRange { const INITIAL_TEX_SIZE: usize = 2; /// Initial size of vertex buffer. TODO: Way of overriding this -const INITIAL_VERT_SIZE: u64 = 32; +const INITIAL_VERT_SIZE: u64 = 3 * 3000; /// Initial size of index buffer. TODO: Way of overriding this -const INITIAL_INDEX_SIZE: u64 = 16; +const INITIAL_INDEX_SIZE: u64 = 3000; /// Source for vertex shader. TODO const VERTEX_SOURCE: &str = include_str!("./data/stockton.vert"); @@ -313,9 +322,7 @@ impl<'a> RenderingContext<'a> { self.device.wait_idle().unwrap(); // Swapchain itself - let old_swapchain = unsafe { - ManuallyDrop::into_inner(read(&self.swapchain)) - }; + let old_swapchain = ManuallyDrop::into_inner(read(&self.swapchain)); let (format, viewport, extent, swapchain, backbuffer) = RenderingContext::create_swapchain(&mut self.surface, &mut self.device, &self.adapter, Some(old_swapchain))?; @@ -326,12 +333,11 @@ impl<'a> RenderingContext<'a> { self.camera.update_aspect_ratio(extent.width as f32 / extent.height as f32); // Graphics pipeline - unsafe { - self.device.destroy_graphics_pipeline(ManuallyDrop::into_inner(read(&self.pipeline))); + self.device.destroy_graphics_pipeline(ManuallyDrop::into_inner(read(&self.pipeline))); - self.device - .destroy_pipeline_layout(ManuallyDrop::into_inner(read(&self.pipeline_layout))); - } + self.device + .destroy_pipeline_layout(ManuallyDrop::into_inner(read(&self.pipeline_layout))); + let (pipeline_layout, pipeline) = { let mut descriptor_set_layouts: ArrayVec<[_; 2]> = ArrayVec::new(); @@ -359,24 +365,22 @@ impl<'a> RenderingContext<'a> { } // Make new ones for i in 0..backbuffer.len() { - unsafe { - use hal::image::ViewKind; - use hal::format::Swizzle; - - self.imageviews.push(self.device.create_image_view( - &backbuffer[i], - ViewKind::D2, - format, - Swizzle::NO, - COLOR_RANGE.clone(), - ).map_err(|e| error::CreationError::ImageViewError (e))?); - - self.framebuffers.push(self.device.create_framebuffer( - &self.renderpass, - Some(&self.imageviews[i]), - extent - ).map_err(|_| error::CreationError::OutOfMemoryError)?); - } + use hal::image::ViewKind; + use hal::format::Swizzle; + + self.imageviews.push(self.device.create_image_view( + &backbuffer[i], + ViewKind::D2, + format, + Swizzle::NO, + COLOR_RANGE.clone(), + ).map_err(|e| error::CreationError::ImageViewError (e))?); + + self.framebuffers.push(self.device.create_framebuffer( + &self.renderpass, + Some(&self.imageviews[i]), + extent + ).map_err(|_| error::CreationError::OutOfMemoryError)?); } Ok(()) @@ -718,6 +722,7 @@ impl<'a> RenderingContext<'a> { Ok(()) } + /// Draw all vertices in the buffer pub fn draw_vertices(&mut self) -> Result<(), &'static str> { let get_image = &self.get_image[self.current_frame]; let render_complete = &self.render_complete[self.current_frame]; @@ -835,6 +840,58 @@ impl<'a> RenderingContext<'a> { Ok(()) } + + /// Get current position of camera + pub fn camera_pos(&self) -> Vector3 { + self.camera.camera_pos() + } + + /// Move the camera by `delta` + pub fn move_camera(&mut self, delta: Vector3) { + self.camera.move_camera(delta) + } + + /// Load all active faces into the vertex buffers for drawing + // TODO: This is just a POC, we need to restructure things a lot for actually texturing, etc + pub fn set_active_faces(&mut self, faces: Vec<usize>, file: &BSPFile) { + let mut curr_vert_idx: usize = 0; + let mut curr_idx_idx: usize = 0; + + for face in faces.into_iter().map(|idx| &file.faces.faces[idx]) { + if face.face_type == FaceType::Polygon || face.face_type == FaceType::Mesh { + let base = face.vertices_idx.start as i32; + + for idx in face.meshverts_idx.clone().step_by(3) { + let start_idx: u16 = curr_vert_idx.try_into().unwrap(); + + for mv in &file.meshverts.meshverts[idx..idx+3] { + let vert = &file.vertices.vertices[(base + mv.offset) as usize]; + let uv = Vector2::new(vert.tex.u[0], vert.tex.v[0]); + + let uvp = UVPoint (vert.position, uv, 0); + self.vert_buffer[curr_vert_idx] = uvp; + + curr_vert_idx += 1; + } + + + self.index_buffer[curr_idx_idx] = (start_idx, start_idx + 1, start_idx + 2); + + curr_idx_idx += 1; + + if curr_vert_idx >= INITIAL_VERT_SIZE.try_into().unwrap() || curr_idx_idx >= INITIAL_INDEX_SIZE.try_into().unwrap() { + break; + } + } + } else { + // TODO: Other types of faces + } + + if curr_vert_idx >= INITIAL_VERT_SIZE.try_into().unwrap() || curr_idx_idx >= INITIAL_INDEX_SIZE.try_into().unwrap() { + break; + } + } + } } impl<'a> core::ops::Drop for RenderingContext<'a> { diff --git a/stockton-render/src/lib.rs b/stockton-render/src/lib.rs index 2255c49..3f157a1 100644 --- a/stockton-render/src/lib.rs +++ b/stockton-render/src/lib.rs @@ -33,18 +33,17 @@ extern crate arrayvec; pub mod draw; mod error; mod types; -mod walk_bsp; - -use std::sync::{Arc, RwLock}; +mod culling; use stockton_types::World; use error::{CreationError, FrameError}; use draw::RenderingContext; +use culling::get_visible_faces; /// Renders a world to a window when you tell it to. pub struct Renderer<'a> { - world: Arc<RwLock<World<'a>>>, + world: World, pub context: RenderingContext<'a> } @@ -52,18 +51,30 @@ pub struct Renderer<'a> { impl<'a> Renderer<'a> { /// Create a new Renderer. /// This initialises all the vulkan context, etc needed. - pub fn new(world: World<'a>, window: &winit::window::Window) -> Result<Self, CreationError> { - let world = Arc::new(RwLock::new(world)); + pub fn new(world: World, window: &winit::window::Window) -> Result<Self, CreationError> { let context = RenderingContext::new(window)?; Ok(Renderer { - world: world, context + world, context }) } /// Render a single frame of the world pub fn render_frame(&mut self) -> Result<(), FrameError>{ - self.context.draw_vertices().unwrap(); + // Get visible faces + let faces = get_visible_faces(self.context.camera_pos(), &self.world.map); + + // Load them in + self.context.set_active_faces(faces, &self.world.map); + + // Then draw them + if let Err(_) = self.context.draw_vertices() { + unsafe {self.context.handle_surface_change().unwrap()}; + + // If it fails twice, then error + self.context.draw_vertices().map_err(|_| FrameError::PresentError)?; + } + Ok(()) } } |