diff --git a/crates/shaders-shared/src/lib.rs b/crates/shaders-shared/src/lib.rs index 14d32cf..338b322 100644 --- a/crates/shaders-shared/src/lib.rs +++ b/crates/shaders-shared/src/lib.rs @@ -1,6 +1,6 @@ #![cfg_attr(target_arch = "spirv", no_std)] -use glam::Mat4; +use glam::{Mat4, Vec3}; #[repr(C)] #[derive(Clone)] @@ -8,4 +8,5 @@ pub struct UniformBufferObject { pub model: Mat4, pub view: Mat4, pub proj: Mat4, + pub model_color: Vec3, } diff --git a/crates/shaders/src/lib.rs b/crates/shaders/src/lib.rs index 68c6d0e..98df01d 100644 --- a/crates/shaders/src/lib.rs +++ b/crates/shaders/src/lib.rs @@ -32,8 +32,13 @@ pub fn main_vs( } #[spirv(fragment)] -pub fn main_fs(frag_world_position: Vec3, frag_world_normal: Vec3, out_color: &mut Vec4) { - let base_color = Vec3::new(1.0, 0.5, 0.5); +pub fn main_fs( + frag_world_position: Vec3, + frag_world_normal: Vec3, + out_color: &mut Vec4, + #[spirv(uniform, descriptor_set = 0, binding = 0)] ubo: &UniformBufferObject, +) { + let base_color = ubo.model_color; let light_pos = Vec3::new(2.0, 2.0, -2.0); // Calculate light direction diff --git a/crates/vk-rs/build.rs b/crates/vk-rs/build.rs index 267e7b2..49f5160 100644 --- a/crates/vk-rs/build.rs +++ b/crates/vk-rs/build.rs @@ -6,6 +6,10 @@ use std::{ use spirv_builder::{MetadataPrintout, SpirvBuilder}; fn main() -> Result<(), Box> { + // Tell Cargo to rerun this script if the shaders crate or its contents change + println!("cargo:rerun-if-changed=../shaders/src"); + println!("cargo:rerun-if-changed=../shaders/Cargo.toml"); + SpirvBuilder::new("../shaders/", "spirv-unknown-vulkan1.2") .print_metadata(MetadataPrintout::None) .multimodule(true) diff --git a/crates/vk-rs/shaders/main_fs.spv b/crates/vk-rs/shaders/main_fs.spv index 1e8b2da..5b57869 100644 Binary files a/crates/vk-rs/shaders/main_fs.spv and b/crates/vk-rs/shaders/main_fs.spv differ diff --git a/crates/vk-rs/shaders/main_vs.spv b/crates/vk-rs/shaders/main_vs.spv index 6332ed0..b94b914 100644 Binary files a/crates/vk-rs/shaders/main_vs.spv and b/crates/vk-rs/shaders/main_vs.spv differ diff --git a/crates/vk-rs/src/main.rs b/crates/vk-rs/src/main.rs index 5a55e99..4aca222 100644 --- a/crates/vk-rs/src/main.rs +++ b/crates/vk-rs/src/main.rs @@ -13,6 +13,7 @@ use ash::{ vk::{self, KhrAccelerationStructureFn, KhrDeferredHostOperationsFn, KhrRayTracingPipelineFn}, Device, Entry, Instance, }; +use egui::widgets; use egui_ash::{ raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}, winit, App, AppCreator, AshRenderState, CreationContext, HandleRedraw, RunOption, Theme, @@ -53,6 +54,9 @@ struct Game { frame_count_since_last_update: i32, current_fps: f32, + bg_color: [f32; 3], + model_color: [f32; 3], + show_profiler: bool, } @@ -112,6 +116,12 @@ impl App for Game { 10.0..=150.0, )); ui.separator(); + + ui.color_edit_button_rgb(&mut self.bg_color); + ui.color_edit_button_rgb(&mut self.model_color); + + ui.separator(); + if ui.button("Show Profiler").clicked() { self.show_profiler = !self.show_profiler; } @@ -220,9 +230,13 @@ impl App for Game { let camera_yaw = self.camera_yaw; let camera_pitch = self.camera_pitch; let camera_fov = self.camera_fov; + + let bg_color = self.bg_color; + let model_color = self.model_color; move |size, egui_cmd| { let mut renderer = renderer.inner.lock().unwrap(); renderer.update_camera(camera_position, camera_yaw, camera_pitch, camera_fov); + renderer.update_colors(bg_color.into(), model_color.into()); renderer.render(size.width, size.height, egui_cmd, rotate_y) } })) @@ -626,6 +640,8 @@ impl AppCreator>> for MyAppCreator { camera_pitch: 0., camera_yaw: 0., camera_fov: 45., + bg_color: Vec3::splat(0.1).into(), + model_color: Vec3::splat(0.8).into(), last_mouse_pos: None, right_mouse_pressed: false, last_fps_update: std::time::Instant::now(), diff --git a/crates/vk-rs/src/renderer.rs b/crates/vk-rs/src/renderer.rs index 732ca02..d6179b7 100644 --- a/crates/vk-rs/src/renderer.rs +++ b/crates/vk-rs/src/renderer.rs @@ -3,6 +3,7 @@ use ash::{ vk::{self, Buffer}, Device, }; +use color_eyre::owo_colors::Color; use egui_ash::EguiCommand; use glam::{Mat4, Vec3}; use gpu_allocator::vulkan::{Allocation, Allocator}; @@ -104,6 +105,8 @@ pub struct RendererInner { camera_fov: f32, camera_yaw: f32, camera_pitch: f32, + bg_color: Vec3, + model_color: Vec3, accumulation_reset_needed: bool, } @@ -199,12 +202,13 @@ impl RendererInner { (swapchain, surface_format, surface_extent, swapchain_images) } - fn create_uniform_buffers( + fn create_uniform_buffers( device: &Device, allocator: Arc>, swapchain_count: usize, ) -> (Vec, Vec) { - let buffer_size = std::mem::size_of::() as u64; + let buffer_size = std::mem::size_of::() as u64; + let buffer_usage = vk::BufferUsageFlags::UNIFORM_BUFFER; let buffer_create_info = vk::BufferCreateInfo::builder() .size(buffer_size) @@ -269,7 +273,7 @@ impl RendererInner { .binding(0) .descriptor_type(vk::DescriptorType::UNIFORM_BUFFER) .descriptor_count(1) - .stage_flags(vk::ShaderStageFlags::VERTEX); + .stage_flags(vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT); let ubo_layout_create_info = vk::DescriptorSetLayoutCreateInfo::builder() .bindings(std::slice::from_ref(&ubo_layout_binding)); @@ -300,7 +304,8 @@ impl RendererInner { let buffer_info = vk::DescriptorBufferInfo::builder() .buffer(uniform_buffers[index]) .offset(0) - .range(vk::WHOLE_SIZE); + .range(vk::WHOLE_SIZE) + .build(); let descriptor_write = vk::WriteDescriptorSet::builder() .dst_set(descriptor_sets[index]) .dst_binding(0) @@ -535,8 +540,8 @@ impl RendererInner { .depth_clamp_enable(false) .rasterizer_discard_enable(false) .polygon_mode(vk::PolygonMode::FILL) - .cull_mode(vk::CullModeFlags::NONE) - .front_face(vk::FrontFace::COUNTER_CLOCKWISE) + .cull_mode(vk::CullModeFlags::BACK) + .front_face(vk::FrontFace::CLOCKWISE) .depth_bias_enable(false) .line_width(1.0); let stencil_op = vk::StencilOpState::builder() @@ -546,7 +551,7 @@ impl RendererInner { let depth_stencil_info = vk::PipelineDepthStencilStateCreateInfo::builder() .depth_test_enable(true) .depth_write_enable(true) - .depth_compare_op(vk::CompareOp::LESS_OR_EQUAL) + .depth_compare_op(vk::CompareOp::LESS) .depth_bounds_test_enable(false) .stencil_test_enable(false) .front(*stencil_op) @@ -792,36 +797,32 @@ impl RendererInner { swapchain_count: usize, ) -> (Vec, Vec, Vec) { let fence_create_info = - vk::FenceCreateInfo::builder().flags(vk::FenceCreateFlags::SIGNALED); - let mut in_flight_fences = vec![]; + vk::FenceCreateInfo::builder().flags(vk::FenceCreateFlags::SIGNALED); // Start signaled + + let semaphore_create_info = vk::SemaphoreCreateInfo::builder(); + + let mut in_flight_fences = Vec::with_capacity(swapchain_count); + let mut image_available_semaphores = Vec::with_capacity(swapchain_count); + let mut render_finished_semaphores = Vec::with_capacity(swapchain_count); + for _ in 0..swapchain_count { - let fence = unsafe { - device + unsafe { + let fence = device .create_fence(&fence_create_info, None) - .expect("Failed to create fence") - }; - in_flight_fences.push(fence); - } - let mut image_available_semaphores = vec![]; - for _ in 0..swapchain_count { - let semaphore_create_info = vk::SemaphoreCreateInfo::builder(); - let semaphore = unsafe { - device + .expect("Failed to create fence"); + let image_available = device .create_semaphore(&semaphore_create_info, None) - .expect("Failed to create semaphore") - }; - image_available_semaphores.push(semaphore); - } - let mut render_finished_semaphores = vec![]; - for _ in 0..swapchain_count { - let semaphore_create_info = vk::SemaphoreCreateInfo::builder(); - let semaphore = unsafe { - device + .expect("Failed to create semaphore"); + let render_finished = device .create_semaphore(&semaphore_create_info, None) - .expect("Failed to create semaphore") - }; - render_finished_semaphores.push(semaphore); + .expect("Failed to create semaphore"); + + in_flight_fences.push(fence); + image_available_semaphores.push(image_available); + render_finished_semaphores.push(render_finished); + } } + ( in_flight_fences, image_available_semaphores, @@ -1004,7 +1005,12 @@ impl RendererInner { height, ); let (uniform_buffers, uniform_buffer_allocations) = - Self::create_uniform_buffers(&device, allocator.clone(), swapchain_images.len()); + Self::create_uniform_buffers::( + &device, + allocator.clone(), + swapchain_images.len(), + ); + let descriptor_pool = Self::create_descriptor_pool(&device, swapchain_images.len()); let descriptor_set_layouts = Self::create_descriptor_set_layouts(&device, swapchain_images.len()); @@ -1083,10 +1089,27 @@ impl RendererInner { camera_yaw: 0., camera_pitch: 0., camera_fov: 45., + bg_color: Vec3::splat(0.1), + model_color: Vec3::splat(0.8), accumulation_reset_needed: true, } } + pub fn update_colors(&mut self, bg_color: Vec3, model_color: Vec3) { + let bg_color = clamped_color(bg_color); + let model_color = clamped_color(model_color); + + if bg_color != self.bg_color { + self.bg_color = bg_color; + self.accumulation_reset_needed = true; + } + + if model_color != self.model_color { + self.model_color = model_color; + self.accumulation_reset_needed = true; + } + } + pub fn update_camera(&mut self, new_position: Vec3, yaw: f32, pitch: f32, fov: f32) { if (new_position - self.camera_position).length() > 0.0001 || (yaw - self.camera_yaw).abs() > 0.001 @@ -1121,23 +1144,21 @@ impl RendererInner { self.recreate_swapchain(width, height, &mut egui_cmd); } - let result = unsafe { - puffin::profile_scope!("acquire_next_image"); - self.swapchain_loader.acquire_next_image( - self.swapchain, - u64::MAX, - self.image_available_semaphores[self.current_frame], - vk::Fence::null(), - ) - }; - let index = match result { - Ok((index, _)) => index as usize, - Err(vk::Result::ERROR_OUT_OF_DATE_KHR) => { - self.dirty_swapchain = true; - return; - } - Err(_) => return, - }; + // unsafe { + // self.device + // .wait_for_fences( + // std::slice::from_ref(&self.in_flight_fences[self.current_frame]), + // true, + // u64::MAX, + // ) + // .expect("failed to wait for fences"); + // + // self.device + // .reset_fences(std::slice::from_ref( + // &self.in_flight_fences[self.current_frame], + // )) + // .expect("failed to reset fences"); + // } unsafe { puffin::profile_scope!("wait_for_fences"); @@ -1156,6 +1177,24 @@ impl RendererInner { } .expect("Failed to reset fences"); + let result = unsafe { + puffin::profile_scope!("acquire_next_image"); + self.swapchain_loader.acquire_next_image( + self.swapchain, + u64::MAX, + self.image_available_semaphores[self.current_frame], + vk::Fence::null(), + ) + }; + let index = match result { + Ok((index, _)) => index as usize, + Err(vk::Result::ERROR_OUT_OF_DATE_KHR) => { + self.dirty_swapchain = true; + return; + } + Err(_) => return, + }; + let view = { puffin::profile_scope!("calculate_view"); let (sin_pitch, cos_pitch) = self.camera_pitch.sin_cos(); @@ -1180,6 +1219,7 @@ impl RendererInner { 0.1, 10.0, ), + model_color: self.model_color, }; unsafe { @@ -1215,7 +1255,7 @@ impl RendererInner { .clear_values(&[ vk::ClearValue { color: vk::ClearColorValue { - float32: [0.4, 0.3, 0.2, 1.0], + float32: [self.bg_color.x, self.bg_color.y, self.bg_color.z, 1.0], }, }, vk::ClearValue { @@ -1388,6 +1428,7 @@ impl RendererInner { for allocation in self.uniform_buffer_allocations.drain(..) { allocator.free(allocation).expect("Failed to free memory"); } + self.swapchain_loader .destroy_swapchain(self.swapchain, None); } @@ -1436,3 +1477,11 @@ impl Renderer { self.inner.lock().unwrap().destroy(); } } + +fn clamped_color(color: Vec3) -> Vec3 { + Vec3::new( + color.x.clamp(0.0, 1.0), + color.y.clamp(0.0, 1.0), + color.z.clamp(0.0, 1.0), + ) +}