diff --git a/shaders/compile.bat b/shaders/compile.bat index 27ac9c4..01e5f2c 100644 --- a/shaders/compile.bat +++ b/shaders/compile.bat @@ -4,4 +4,7 @@ C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/cube.geom -o shaders/geo_cube.spv C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/cuboid.vert -o shaders/vert_cuboid.spv C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/cuboid.frag -o shaders/frag_cuboid.spv -C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/cuboid.geom -o shaders/geo_cuboid.spv \ No newline at end of file +C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/cuboid.geom -o shaders/geo_cuboid.spv + +C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_quad.vert -o shaders/vert_rt_quad.spv +C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_quad.frag -o shaders/frag_rt_quad.spv \ No newline at end of file diff --git a/shaders/frag_rt_quad.spv b/shaders/frag_rt_quad.spv new file mode 100644 index 0000000..50157c9 Binary files /dev/null and b/shaders/frag_rt_quad.spv differ diff --git a/shaders/rt_quad.frag b/shaders/rt_quad.frag new file mode 100644 index 0000000..ffaa3b5 --- /dev/null +++ b/shaders/rt_quad.frag @@ -0,0 +1,10 @@ +#version 450 + +layout(location = 0) flat in uvec2 fragRasterPos; +layout(location = 1) flat in uint fragVolumeStart; + +layout(location = 0) out vec4 outColor; + +void main() { + outColor = vec4(1, 0, 0, 1); +} \ No newline at end of file diff --git a/shaders/rt_quad.vert b/shaders/rt_quad.vert new file mode 100644 index 0000000..4b679a4 --- /dev/null +++ b/shaders/rt_quad.vert @@ -0,0 +1,27 @@ +#version 450 + +layout(binding = 0) uniform UniformBufferObject { + mat4 model; + mat4 geom_rot; + mat4 view; + mat4 proj; + bool[16] use_geom_shader; +} ubo; + + +layout(location = 0) in vec3 inPosition; +layout(location = 1) in uvec2 inRasterPos; +layout(location = 2) in uint inVolumeStart; + +layout(location = 0) out uvec2 rasterPos; +layout(location = 1) out uint volumeStart; + +void main() { + if (ubo.use_geom_shader[0]) { + gl_Position = ubo.geom_rot * ubo.model * vec4(inPosition, 1.0); + } else { + gl_Position = ubo.proj * ubo.view * ubo.geom_rot * ubo.model * vec4(inPosition, 1.0); + } + rasterPos = inRasterPos; + volumeStart = inVolumeStart; +} \ No newline at end of file diff --git a/shaders/vert_rt_quad.spv b/shaders/vert_rt_quad.spv new file mode 100644 index 0000000..62118cc Binary files /dev/null and b/shaders/vert_rt_quad.spv differ diff --git a/src/app_data.rs b/src/app_data.rs index 71a99e6..fcf3f73 100644 --- a/src/app_data.rs +++ b/src/app_data.rs @@ -21,6 +21,7 @@ pub struct AppData { pub render_pass: vk::RenderPass, pub pipeline_cube: vk::Pipeline, pub pipeline_cuboid: vk::Pipeline, + pub pipeline_quad: vk::Pipeline, pub framebuffers: Vec, pub command_pool: vk::CommandPool, pub command_buffers: Vec, diff --git a/src/command_buffer.rs b/src/command_buffer.rs index f9c5a68..050e21c 100644 --- a/src/command_buffer.rs +++ b/src/command_buffer.rs @@ -107,6 +107,26 @@ pub unsafe fn create_command_buffers(device: &Device, data: &mut app_data::AppDa device.cmd_draw_indexed(*command_buffer, scene_handler.indices_cuboid.len() as u32, 1, 0, 0, 0); } + if scene_handler.rt_vertices.len() != 0 { + device.cmd_bind_pipeline( + *command_buffer, vk::PipelineBindPoint::GRAPHICS, data.pipeline_quad); //todo build own pipeline + + device.cmd_bind_vertex_buffers(*command_buffer, 0, &[scene_handler.vertex_buffer_quad], &[0]); + device.cmd_bind_index_buffer(*command_buffer, scene_handler.index_buffer_quad, 0, vk::IndexType::UINT32); + + + device.cmd_bind_descriptor_sets( + *command_buffer, + vk::PipelineBindPoint::GRAPHICS, + data.pipeline_layout, + 0, + &[data.descriptor_sets[i]], + &[], + ); + + device.cmd_draw_indexed(*command_buffer, scene_handler.indices_rt.len() as u32, 1, 0, 0, 0); + } + device.cmd_end_render_pass(*command_buffer); device.end_command_buffer(*command_buffer)?; diff --git a/src/main.rs b/src/main.rs index 5fa20a9..1118eb0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -365,6 +365,7 @@ impl App { self.device.free_command_buffers(self.data.command_pool, &self.data.command_buffers); self.device.destroy_pipeline(self.data.pipeline_cube, None); self.device.destroy_pipeline(self.data.pipeline_cuboid, None); + self.device.destroy_pipeline(self.data.pipeline_quad, None); self.device.destroy_pipeline_layout(self.data.pipeline_layout, None); self.device.destroy_render_pass(self.data.render_pass, None); self.data.swapchain_image_views @@ -668,64 +669,93 @@ unsafe fn create_logical_device( } unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Result<()> { + // set up shaders for cubes + // load the byte data let vert_cube = include_bytes!("../shaders/vert_cube.spv"); let geo_cube = include_bytes!("../shaders/geo_cube.spv"); let frag_cube = include_bytes!("../shaders/frag_cube.spv"); - + // create the shaders let vert_shader_module_cube = create_shader_module(device, &vert_cube[..])?; let geo_shader_module_cube = create_shader_module(device, &geo_cube[..])?; let frag_shader_module_cube = create_shader_module(device, &frag_cube[..])?; - + //create the shader stage for the vertex shader let vert_stage_cube = vk::PipelineShaderStageCreateInfo::builder() .stage(vk::ShaderStageFlags::VERTEX) .module(vert_shader_module_cube) .name(b"main\0"); - + //create the shader stage for the geometry shader let geo_stage_cube = vk::PipelineShaderStageCreateInfo::builder() .stage(vk::ShaderStageFlags::GEOMETRY) .module(geo_shader_module_cube) .name(b"main\0"); - + //create the shader stage for the fragment shader let frag_stage_cube = vk::PipelineShaderStageCreateInfo::builder() .stage(vk::ShaderStageFlags::FRAGMENT) .module(frag_shader_module_cube) .name(b"main\0"); - + // create the binding description for the cube vertex let binding_descriptions_cube = &[vertex::Vertex::binding_description()]; let attribute_descriptions_cube = vertex::Vertex::attribute_descriptions(); let vertex_input_state_cube = vk::PipelineVertexInputStateCreateInfo::builder() .vertex_binding_descriptions(binding_descriptions_cube) .vertex_attribute_descriptions(&attribute_descriptions_cube); + // set up shaders for cuboids + // load the byte data let vert_cuboid = include_bytes!("../shaders/vert_cuboid.spv"); let geo_cuboid = include_bytes!("../shaders/geo_cuboid.spv"); let frag_cuboid = include_bytes!("../shaders/frag_cuboid.spv"); - + // create the shaders let vert_shader_module_cuboid = create_shader_module(device, &vert_cuboid[..])?; let geo_shader_module_cuboid = create_shader_module(device, &geo_cuboid[..])?; let frag_shader_module_cuboid = create_shader_module(device, &frag_cuboid[..])?; - + //create the shader stage for the vertex shader let vert_stage_cuboid = vk::PipelineShaderStageCreateInfo::builder() .stage(vk::ShaderStageFlags::VERTEX) .module(vert_shader_module_cuboid) .name(b"main\0"); - + //create the shader stage for the geometry shader let geo_stage_cuboid = vk::PipelineShaderStageCreateInfo::builder() .stage(vk::ShaderStageFlags::GEOMETRY) .module(geo_shader_module_cuboid) .name(b"main\0"); - + //create the shader stage for the fragment shader let frag_stage_cuboid = vk::PipelineShaderStageCreateInfo::builder() .stage(vk::ShaderStageFlags::FRAGMENT) .module(frag_shader_module_cuboid) .name(b"main\0"); - + // create the binding description for the sized vertex let binding_descriptions_cuboid = &[vertex::SizedVertex::binding_description()]; let attribute_descriptions_cuboid = vertex::SizedVertex::attribute_descriptions(); let vertex_input_state_cuboid = vk::PipelineVertexInputStateCreateInfo::builder() .vertex_binding_descriptions(binding_descriptions_cuboid) .vertex_attribute_descriptions(&attribute_descriptions_cuboid); + // set up shaders for quads/raytracing + // load the byte data + let vert_quad = include_bytes!("../shaders/vert_rt_quad.spv"); + let frag_quad = include_bytes!("../shaders/frag_rt_quad.spv"); + // create the shaders + let vert_shader_module_quad = create_shader_module(device, &vert_quad[..])?; + let frag_shader_module_quad = create_shader_module(device, &frag_quad[..])?; + //create the shader stage for the vertex shader + let vert_stage_quad = vk::PipelineShaderStageCreateInfo::builder() + .stage(vk::ShaderStageFlags::VERTEX) + .module(vert_shader_module_quad) + .name(b"main\0"); + //create the shader stage for the fragment shader + let frag_stage_quad = vk::PipelineShaderStageCreateInfo::builder() + .stage(vk::ShaderStageFlags::FRAGMENT) + .module(frag_shader_module_quad) + .name(b"main\0"); + // create the binding description for the quad vertex + let binding_descriptions_quad = &[vertex::RTVertex::binding_description()]; + let attribute_descriptions_quad = vertex::RTVertex::attribute_descriptions(); + let vertex_input_state_quad = vk::PipelineVertexInputStateCreateInfo::builder() + .vertex_binding_descriptions(binding_descriptions_quad) + .vertex_attribute_descriptions(&attribute_descriptions_quad); + + // define input assembly and object type. This is altered when using geometry shader let mut topology = vk::PrimitiveTopology::TRIANGLE_LIST; if data.use_geometry_shader { topology = vk::PrimitiveTopology::POINT_LIST; @@ -736,6 +766,7 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu .topology(topology) .primitive_restart_enable(false); + // define viewport and other transformations when projecting onto the screen let viewport = vk::Viewport::builder() .x(0.0) .y(0.0) @@ -793,12 +824,13 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu .attachments(attachments) .blend_constants([0.0, 0.0, 0.0, 0.0]); + // define the work pipeline let set_layouts = &[data.descriptor_set_layout]; let layout_info = vk::PipelineLayoutCreateInfo::builder() .set_layouts(set_layouts); data.pipeline_layout = device.create_pipeline_layout(&layout_info, None)?; - + // define stages for the cubes pipeline let stages_cube = &[vert_stage_cube, frag_stage_cube]; let stages_geom_cube = &[vert_stage_cube, geo_stage_cube,frag_stage_cube]; @@ -820,7 +852,7 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu else { info_cube = info_cube.stages(stages_cube); } - + // define stages for the cuboid pipeline let stages_cuboid = &[vert_stage_cuboid, frag_stage_cuboid]; let stages_geom_cuboid = &[vert_stage_cuboid, geo_stage_cuboid,frag_stage_cuboid]; @@ -842,11 +874,30 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu else { info_cuboid = info_cuboid.stages(stages_cuboid); } + // define stages for the quad/rt pipeline + let stages_quad = &[vert_stage_quad, frag_stage_quad]; - let pipelines = device.create_graphics_pipelines(vk::PipelineCache::null(), &[info_cube, info_cuboid], None)?.0; + let mut info_quad = vk::GraphicsPipelineCreateInfo::builder() + .vertex_input_state(&vertex_input_state_quad) + .input_assembly_state(&input_assembly_state) + .viewport_state(&viewport_state) + .rasterization_state(&rasterization_state) + .multisample_state(&multisample_state) + .depth_stencil_state(&depth_stencil_state) + .color_blend_state(&color_blend_state) + .layout(data.pipeline_layout) + .render_pass(data.render_pass) + .subpass(0); + + + info_quad = info_quad.stages(stages_quad); + + // create the pipeline + let pipelines = device.create_graphics_pipelines(vk::PipelineCache::null(), &[info_cube, info_cuboid, info_quad], None)?.0; data.pipeline_cube = pipelines[0]; data.pipeline_cuboid = pipelines[1]; + data.pipeline_quad = pipelines[2]; device.destroy_shader_module(vert_shader_module_cube, None); device.destroy_shader_module(geo_shader_module_cube, None); @@ -856,6 +907,9 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu device.destroy_shader_module(geo_shader_module_cuboid, None); device.destroy_shader_module(frag_shader_module_cuboid, None); + device.destroy_shader_module(vert_shader_module_quad, None); + device.destroy_shader_module(frag_shader_module_quad, None); + Ok(()) } diff --git a/src/primitives/cube.rs b/src/primitives/cube.rs index cfc75b4..fd27a1e 100644 --- a/src/primitives/cube.rs +++ b/src/primitives/cube.rs @@ -11,55 +11,57 @@ pub struct Cube{ pub tex_coord: vertex::Vec2 } +const cube_size: f32 = 0.48; + impl Drawable for Cube { fn draw(& self, topology: &vk::PrimitiveTopology, start_index: usize, scene: &mut Scene) { if *topology == vk::PrimitiveTopology::TRIANGLE_LIST { // 0 top left far scene.vertices.push(vertex::Vertex::new( - vec3(self.pos.x as f32 - 0.5, self.pos.y as f32 + 0.5, self.pos.z as f32 + 0.5), + vec3(self.pos.x as f32 - cube_size, self.pos.y as f32 + cube_size, self.pos.z as f32 + cube_size), self.color, self.tex_coord )); // 1 top right far scene.vertices.push(vertex::Vertex::new( - vec3(self.pos.x as f32 + 0.5, self.pos.y as f32 + 0.5, self.pos.z as f32 + 0.5), + vec3(self.pos.x as f32 + cube_size, self.pos.y as f32 + cube_size, self.pos.z as f32 + cube_size), self.color, self.tex_coord )); // 2 top left near scene.vertices.push(vertex::Vertex::new( - vec3(self.pos.x as f32 - 0.5, self.pos.y as f32 - 0.5, self.pos.z as f32 + 0.5), + vec3(self.pos.x as f32 - cube_size, self.pos.y as f32 - cube_size, self.pos.z as f32 + cube_size), self.color, self.tex_coord )); // 3 top right near scene.vertices.push(vertex::Vertex::new( - vec3(self.pos.x as f32 + 0.5, self.pos.y as f32 - 0.5, self.pos.z as f32 + 0.5), + vec3(self.pos.x as f32 + cube_size, self.pos.y as f32 - cube_size, self.pos.z as f32 + cube_size), self.color, self.tex_coord )); // 4 bottom left far scene.vertices.push(vertex::Vertex::new( - vec3(self.pos.x as f32 - 0.5, self.pos.y as f32 + 0.5, self.pos.z as f32 - 0.5), + vec3(self.pos.x as f32 - cube_size, self.pos.y as f32 + cube_size, self.pos.z as f32 - cube_size), self.color, self.tex_coord )); // 5 bottom right far scene.vertices.push(vertex::Vertex::new( - vec3(self.pos.x as f32 + 0.5, self.pos.y as f32 + 0.5, self.pos.z as f32 - 0.5), + vec3(self.pos.x as f32 + cube_size, self.pos.y as f32 + cube_size, self.pos.z as f32 - cube_size), self.color, self.tex_coord )); // 6 bottom left near scene.vertices.push(vertex::Vertex::new( - vec3(self.pos.x as f32 - 0.5, self.pos.y as f32 - 0.5, self.pos.z as f32 - 0.5), + vec3(self.pos.x as f32 - cube_size, self.pos.y as f32 - cube_size, self.pos.z as f32 - cube_size), self.color, self.tex_coord )); // 7 bottom right near scene.vertices.push(vertex::Vertex::new( - vec3(self.pos.x as f32 + 0.5, self.pos.y as f32 - 0.5, self.pos.z as f32 - 0.5), + vec3(self.pos.x as f32 + cube_size, self.pos.y as f32 - cube_size, self.pos.z as f32 - cube_size), self.color, self.tex_coord )); diff --git a/src/primitives/mod.rs b/src/primitives/mod.rs index 7b1f5d3..261af80 100644 --- a/src/primitives/mod.rs +++ b/src/primitives/mod.rs @@ -1,3 +1,4 @@ pub mod cube; pub mod rec_cuboid; +pub mod quad; pub mod drawable; \ No newline at end of file diff --git a/src/primitives/quad.rs b/src/primitives/quad.rs new file mode 100644 index 0000000..0068e27 --- /dev/null +++ b/src/primitives/quad.rs @@ -0,0 +1,55 @@ +use vulkanalia::prelude::v1_0::*; +use cgmath::vec3; +use crate::vertex; +use crate::scene::Scene; +use crate::primitives::drawable::Drawable; + +#[derive(Clone, Debug, PartialEq)] +pub struct Quad{ + pub pos1: vertex::Vec3, + pub pos2: vertex::Vec3, + pub pos3: vertex::Vec3, + pub pos4: vertex::Vec3, + pub raster_pos: cgmath::Vector2, + pub volume_index: u32, +} + +impl Drawable for Quad { + fn draw(& self, topology: &vk::PrimitiveTopology, start_index: usize, scene: &mut Scene) { + if *topology == vk::PrimitiveTopology::TRIANGLE_LIST { + // 0 top left far + scene.rt_vertices.push(vertex::RTVertex::new( + vec3(self.pos1.x as f32, self.pos1.y as f32, self.pos1.z as f32), + self.raster_pos, + self.volume_index + )); + // 1 top right far + scene.rt_vertices.push(vertex::RTVertex::new( + vec3(self.pos2.x as f32, self.pos2.y as f32, self.pos2.z as f32), + self.raster_pos, + self.volume_index + )); + // 2 top left near + scene.rt_vertices.push(vertex::RTVertex::new( + vec3(self.pos3.x as f32, self.pos3.y as f32, self.pos3.z as f32), + self.raster_pos, + self.volume_index + )); + // 3 top right near + scene.rt_vertices.push(vertex::RTVertex::new( + vec3(self.pos4.x as f32, self.pos4.y as f32, self.pos4.z as f32), + self.raster_pos, + self.volume_index + )); + + // top + scene.indices_rt.push(start_index as u32 + 2); + scene.indices_rt.push(start_index as u32 + 1); + scene.indices_rt.push(start_index as u32 + 0); + + scene.indices_rt.push(start_index as u32 + 0); + scene.indices_rt.push(start_index as u32 + 3); + scene.indices_rt.push(start_index as u32 + 2); + } + } +} \ No newline at end of file diff --git a/src/scene.rs b/src/scene.rs index f5bc778..2b12710 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -7,27 +7,32 @@ use cgmath::{vec2, vec3, Vector3}; use std::cell::RefCell; use std::rc::Rc; +use std::time::Instant; + use crate::app_data::AppData; use crate::buffer; use crate::primitives::rec_cuboid::Cuboid; use crate::vertex; use crate::primitives::cube::Cube; +use crate::primitives::quad::Quad; use crate::primitives::drawable::Drawable; extern crate rand; use rand::Rng; -const CHUNK_SIZE_EXPONENT: u32 = 9; +const CHUNK_SIZE_EXPONENT: u32 = 6; const CHUNK_SIZE: usize = (2 as usize).pow(CHUNK_SIZE_EXPONENT); -const MAX_TREE_DEPTH: usize = 7; +const MAX_TREE_DEPTH: usize = 4; const MIN_CHUNK_SIZE: usize = CHUNK_SIZE / (2 as usize).pow(MAX_TREE_DEPTH as u32); #[derive(Clone, Debug, Default)] pub struct Scene { pub vertices: Vec, pub sized_vertices: Vec, + pub rt_vertices: Vec, pub indices_cube: Vec, pub indices_cuboid: Vec, + pub indices_rt: Vec, pub vertex_buffer_cube: vk::Buffer, pub vertex_buffer_memory_cube: vk::DeviceMemory, @@ -40,18 +45,22 @@ pub struct Scene { pub index_buffer_cuboid: vk::Buffer, pub index_buffer_memory_cuboid: vk::DeviceMemory, + + pub vertex_buffer_quad: vk::Buffer, + pub vertex_buffer_memory_quad: vk::DeviceMemory, + + pub index_buffer_quad: vk::Buffer, + pub index_buffer_memory_quad: vk::DeviceMemory, } impl Scene { pub unsafe fn prepare_data(&mut self, instance: &vulkanalia::Instance, device: &vulkanalia::Device, data: &AppData) -> Result<()> { let mut rng = rand::thread_rng(); - let grid_size = 512; //CHUNK_SIZE as i32; + let grid_size = CHUNK_SIZE as i32; // todo store the chunks somewhere (or only use them as intermediary for neighbouthood calculation idc) let mut oct_tree: OctTree = OctTree::create(CHUNK_SIZE)?; - //todo use the 14 vertice box method. Not using geometry shaders seems to be faster... make this a setting? - // have cube elements with a method asking for vertices, while giving a primitive type -> method for preferred primitive type as well as one collecting all primitives for x_index in 0..grid_size { for y_index in 0..grid_size { let shade = (rng.gen_range(0..25) as f32) / 100.0; @@ -65,8 +74,18 @@ impl Scene { } } - let mut test = EmptyVolume::from_oct_tree(&oct_tree); - println!("number of empty volumes is {}", test.len()); + let shade = (rng.gen_range(0..25) as f32) / 100.0; + let cube = Cube { + pos: vec3(10.0, 10.0, 10.0), + color: vec3(shade, 1.0, shade), + tex_coord: vec2(0.0, 0.0) + }; + + oct_tree.set_cube(cube.clone()); + + let mut empty_volumes: Vec>>; + (empty_volumes, _) = EmptyVolume::from_oct_tree(&oct_tree); + println!("number of empty volumes is {}", empty_volumes.len()); let oct_tree_iter = OctTreeIter::create(&oct_tree)?; for item in oct_tree_iter { @@ -74,7 +93,7 @@ impl Scene { let index = self.vertices.len(); match item { Some(cube) => { - if (cube.pos.x + cube.pos.y) as usize % 2 == 0{ + /*if (cube.pos.x + cube.pos.y) as usize % 2 == 0{ /**/ let cuboid = Cuboid { pos: cube.pos, @@ -86,11 +105,19 @@ impl Scene { } else { cube.draw(&data.topology, index, self); - } + }*/ + cube.draw(&data.topology, index, self); } None => {} } } + + for volume in empty_volumes { + let quads = volume.borrow().to_quads(); + for quad in quads { + quad.draw(&data.topology, self.rt_vertices.len(), self); + } + } if self.vertices.len() != 0 { (self.vertex_buffer_cube, self.vertex_buffer_memory_cube) = buffer::create_vertex_buffer(instance, device, &data, &self.vertices)?; @@ -102,6 +129,11 @@ impl Scene { (self.index_buffer_cuboid, self.index_buffer_memory_cuboid) = buffer::create_index_buffer(&instance, &device, &data, &self.indices_cuboid)?; } + if self.rt_vertices.len() != 0 { + (self.vertex_buffer_quad, self.vertex_buffer_memory_quad) = buffer::create_vertex_buffer(instance, device, &data, &self.rt_vertices)?; + (self.index_buffer_quad, self.index_buffer_memory_quad) = buffer::create_index_buffer(&instance, &device, &data, &self.indices_rt)?; + } + Ok(()) } @@ -117,7 +149,13 @@ impl Scene { device.free_memory(self.index_buffer_memory_cuboid, None); device.destroy_buffer(self.vertex_buffer_cuboid, None); - device.free_memory(self.vertex_buffer_memory_cuboid, None); + device.free_memory(self.vertex_buffer_memory_cuboid, None); + + device.destroy_buffer(self.index_buffer_quad, None); + device.free_memory(self.index_buffer_memory_quad, None); + + device.destroy_buffer(self.vertex_buffer_quad, None); + device.free_memory(self.vertex_buffer_memory_quad, None); } } @@ -617,22 +655,22 @@ struct EmptyVolume { pub color_back: Vec>, pub color_top: Vec>, pub color_bottom: Vec>, - pub color_left: Vec>, - pub color_right: Vec>, + pub color_back_rn: Vec>, + pub color_front_rn: Vec>, pub roughness_front: Vec>, pub roughness_back: Vec>, pub roughness_top: Vec>, pub roughness_bottom: Vec>, - pub roughness_left: Vec>, - pub roughness_right: Vec>, + pub roughness_back_rn: Vec>, + pub roughness_front_rn: Vec>, - pub neighbor_front: Vec>>, - pub neighbor_back: Vec>>, - pub neighbor_top: Vec>>, - pub neighbor_bottom: Vec>>, - pub neighbor_left: Vec>>, - pub neighbor_right: Vec>>, + pub neighbor_front: Vec>>>, + pub neighbor_back: Vec>>>, + pub neighbor_top: Vec>>>, + pub neighbor_bottom: Vec>>>, + pub neighbor_back_rn: Vec>>>, + pub neighbor_front_rn: Vec>>>, } impl EmptyVolume { @@ -642,11 +680,12 @@ impl EmptyVolume { self.position[2] + self.size_z > pos[2] && pos[2] >= self.position[2] } - pub fn from_oct_tree(tree: &OctTree) -> Vec>> { + pub fn from_oct_tree(tree: &OctTree) -> (Vec>>, OctTree>>) { + // todo: ppotentially use a child exist check while going through the oct tree to find some obvios starting empty volumes. Will still need to check for possible expansions though let mut volumes: Vec>> = vec![]; let mut neighbors: OctTree>> = OctTree::create(tree.size).unwrap(); - + let start_time = Instant::now(); // iterate over all block positions in the oct tree for x_index in 0..tree.size { for y_index in 0..tree.size { @@ -664,6 +703,7 @@ impl EmptyVolume { for volume in &volumes { if volume.borrow().contains(&Vector3{x: x_index, y: y_index, z: z_index}) { contained = true; + break; } } if contained { @@ -736,20 +776,20 @@ impl EmptyVolume { color_back: vec![], color_top: vec![], color_bottom: vec![], - color_left: vec![], - color_right: vec![], + color_back_rn: vec![], + color_front_rn: vec![], roughness_front: vec![], roughness_back: vec![], roughness_top: vec![], roughness_bottom: vec![], - roughness_left: vec![], - roughness_right: vec![], + roughness_back_rn: vec![], + roughness_front_rn: vec![], neighbor_front: vec![], neighbor_back: vec![], neighbor_top: vec![], neighbor_bottom: vec![], - neighbor_left: vec![], - neighbor_right: vec![], + neighbor_back_rn: vec![], + neighbor_front_rn: vec![], }; println!("adding neighbor references"); //fill in info in the neighbor octtree @@ -757,12 +797,202 @@ impl EmptyVolume { for x in 0..x_size+1 { for y in 0..y_size+1 { for z in 0..z_size+1 { + // fill only the edges if x == 0 || x == x_size || y == 0 || y == y_size || z==0 || z == z_size { neighbors.set_element(reference.clone(), reference.borrow().position.x + x, reference.borrow().position.y + y, reference.borrow().position.z + z) } } } } + println!("add the border information for color and roughness"); + let x_min_pos; + if reference.borrow().position.x == 0 { + // will result in an empty color and roughness map. + x_min_pos = 0; + } + else { + x_min_pos = reference.borrow().position.x -1; + } + let y_min_pos; + if reference.borrow().position.y == 0 { + // will result in an empty color and roughness map. + y_min_pos = 0; + } + else { + y_min_pos = reference.borrow().position.y -1; + } + let z_min_pos; + if reference.borrow().position.z == 0 { + // will result in an empty color and roughness map. + z_min_pos = 0; + } + else { + z_min_pos = reference.borrow().position.z -1; + } + let x_max_pos = reference.borrow().position.x + reference.borrow().size_x; + let y_max_pos = reference.borrow().position.y + reference.borrow().size_y; + let z_max_pos = reference.borrow().position.z + reference.borrow().size_z; + // bottom face of the volume + let mut bottom_colors = vec![]; + let mut bottom_roughness = vec![]; + let mut bottom_elements_num = 0; + for x in 0..x_size+1 { + for y in 0..y_size+1 { + if let Some(c) = tree.get_element(reference.borrow().position.x + x, reference.borrow().position.y + y, z_min_pos) { + bottom_elements_num += 1; + let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8}; + bottom_colors.push(u8_color); + bottom_roughness.push(Vector3 {x: 128, y: 128, z: 128}); + } + else { + bottom_colors.push(Vector3 { x: 255, y: 255, z: 255 }); + bottom_roughness.push(Vector3 {x: 255, y: 255, z: 255}); + } + } + } + if bottom_elements_num > 0 { + reference.borrow_mut().color_bottom = bottom_colors; + reference.borrow_mut().roughness_bottom = bottom_roughness; + } + else { + reference.borrow_mut().color_bottom= vec![]; + reference.borrow_mut().roughness_bottom= vec![]; + } + // top face of the volume + let mut top_colors = vec![]; + let mut top_roughness = vec![]; + let mut top_elements_num = 0; + for x in 0..x_size+1 { + for y in 0..y_size+1 { + if let Some(c) = tree.get_element(reference.borrow().position.x + x, reference.borrow().position.y + y, z_max_pos) { + top_elements_num += 1; + let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8}; + top_colors.push(u8_color); + top_roughness.push(Vector3 {x: 128, y: 128, z: 128}); + } + else { + top_colors.push(Vector3 { x: 255, y: 255, z: 255 }); + top_roughness.push(Vector3 {x: 255, y: 255, z: 255}); + } + } + } + if top_elements_num > 0 { + reference.borrow_mut().color_top = top_colors; + reference.borrow_mut().roughness_top = top_roughness; + } + else { + reference.borrow_mut().color_top= vec![]; + reference.borrow_mut().roughness_top= vec![]; + } + + // back face of the volume + let mut back_colors_rn = vec![]; + let mut back_roughness_rn = vec![]; + let mut back_elements_num_rn = 0; + for x in 0..x_size+1 { + for z in 0..z_size+1 { + if let Some(c) = tree.get_element(reference.borrow().position.x + x, y_max_pos, reference.borrow().position.z + z) { + back_elements_num_rn += 1; + let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8}; + back_colors_rn.push(u8_color); + back_roughness_rn.push(Vector3 {x: 128, y: 128, z: 128}); + } + else { + back_colors_rn.push(Vector3 { x: 255, y: 255, z: 255 }); + back_roughness_rn.push(Vector3 {x: 255, y: 255, z: 255}); + } + } + } + if back_elements_num_rn > 0 { + reference.borrow_mut().color_back_rn = back_colors_rn; + reference.borrow_mut().roughness_back_rn = back_roughness_rn; + } + else { + reference.borrow_mut().color_back_rn= vec![]; + reference.borrow_mut().roughness_back_rn= vec![]; + } + + // front face of the volume + let mut front_colors_rn = vec![]; + let mut front_roughness_rn = vec![]; + let mut front_elements_num_rn = 0; + for x in 0..x_size+1 { + for z in 0..z_size+1 { + if let Some(c) = tree.get_element(reference.borrow().position.x + x, y_min_pos, reference.borrow().position.z + z) { + front_elements_num_rn += 1; + let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8}; + front_colors_rn.push(u8_color); + front_roughness_rn.push(Vector3 {x: 128, y: 128, z: 128}); + } + else { + front_colors_rn.push(Vector3 { x: 255, y: 255, z: 255 }); + front_roughness_rn.push(Vector3 {x: 255, y: 255, z: 255}); + } + } + } + if front_elements_num_rn > 0 { + reference.borrow_mut().color_front_rn = front_colors_rn; + reference.borrow_mut().roughness_front_rn = front_roughness_rn; + } + else { + reference.borrow_mut().color_front_rn= vec![]; + reference.borrow_mut().roughness_front_rn= vec![]; + } + + // front face of the volume + let mut front_colors = vec![]; + let mut front_roughness = vec![]; + let mut front_elements_num = 0; + for y in 0..y_size+1 { + for z in 0..z_size+1 { + if let Some(c) = tree.get_element(x_min_pos, reference.borrow().position.y + y, reference.borrow().position.z + z) { + front_elements_num += 1; + let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8}; + front_colors.push(u8_color); + front_roughness.push(Vector3 {x: 128, y: 128, z: 128}); + } + else { + front_colors.push(Vector3 { x: 255, y: 255, z: 255 }); + front_roughness.push(Vector3 {x: 255, y: 255, z: 255}); + } + } + } + if front_elements_num > 0 { + reference.borrow_mut().color_front = front_colors; + reference.borrow_mut().roughness_front = front_roughness; + } + else { + reference.borrow_mut().color_front= vec![]; + reference.borrow_mut().roughness_front= vec![]; + } + + // back face of the volume + let mut back_colors = vec![]; + let mut back_roughness = vec![]; + let mut back_elements_num = 0; + for y in 0..y_size+1 { + for z in 0..z_size+1 { + if let Some(c) = tree.get_element(x_max_pos, reference.borrow().position.y + y, reference.borrow().position.z + z) { + back_elements_num += 1; + let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8}; + back_colors.push(u8_color); + back_roughness.push(Vector3 {x: 128, y: 128, z: 128}); + } + else { + back_colors.push(Vector3 { x: 255, y: 255, z: 255 }); + back_roughness.push(Vector3 {x: 255, y: 255, z: 255}); + } + } + } + if back_elements_num > 0 { + reference.borrow_mut().color_back = back_colors; + reference.borrow_mut().roughness_back = back_roughness; + } + else { + reference.borrow_mut().color_back= vec![]; + reference.borrow_mut().roughness_back= vec![]; + } + println!("new volume done"); //push to the list volumes.push(reference); @@ -771,8 +1001,268 @@ impl EmptyVolume { } } } + println!("add the neighbor linkage for all the volumes of the oct tree"); + for reference in volumes.iter_mut() { + let x_min_pos; + if reference.borrow().position.x == 0 { + // will result in an empty color and roughness map. + x_min_pos = 0; + } + else { + x_min_pos = reference.borrow().position.x -1; + } + let y_min_pos; + if reference.borrow().position.y == 0 { + // will result in an empty color and roughness map. + y_min_pos = 0; + } + else { + y_min_pos = reference.borrow().position.y -1; + } + let z_min_pos; + if reference.borrow().position.z == 0 { + // will result in an empty color and roughness map. + z_min_pos = 0; + } + else { + z_min_pos = reference.borrow().position.z -1; + } + let x_max_pos = reference.borrow().position.x + reference.borrow().size_x; + let y_max_pos = reference.borrow().position.y + reference.borrow().size_y; + let z_max_pos = reference.borrow().position.z + reference.borrow().size_z; + // bottom face of the volume + let mut bottom_neighbors = vec![]; + let mut bottom_elements_num = 0; + if z_min_pos != 0 { + for x in 0..reference.borrow().size_x { + for y in 0..reference.borrow().size_y { + if let Some(c) = neighbors.get_element(reference.borrow().position.x + x, reference.borrow().position.y + y, z_min_pos) { + bottom_elements_num += 1; + bottom_neighbors.push(Some(c.clone())); + } + else { + bottom_neighbors.push(None); + } + } + } + } + if bottom_elements_num > 0 { + reference.borrow_mut().neighbor_bottom = bottom_neighbors; + } + else { + reference.borrow_mut().neighbor_bottom = vec![None]; + } + // top face of the volume + let mut top_neighbors = vec![]; + let mut top_elements_num = 0; + for x in 0..reference.borrow().size_x { + for y in 0..reference.borrow().size_y { + if let Some(c) = neighbors.get_element(reference.borrow().position.x + x, reference.borrow().position.y + y, z_max_pos) { + top_elements_num += 1; + top_neighbors.push(Some(c.clone())); + } + else { + top_neighbors.push(None); + } + } + } + if top_elements_num > 0 { + reference.borrow_mut().neighbor_top = top_neighbors; + } + else { + reference.borrow_mut().neighbor_top = vec![None]; + } - volumes + // left face of the volume + let mut back_neighbors_rn = vec![]; + let mut back_elements_num_rn = 0; + for x in 0..reference.borrow().size_x { + for z in 0..reference.borrow().size_z { + if let Some(c) = neighbors.get_element(reference.borrow().position.x + x, y_max_pos, reference.borrow().position.z + z) { + back_elements_num_rn += 1; + back_neighbors_rn.push(Some(c.clone())); + } + else { + back_neighbors_rn.push(None); + } + } + } + if back_elements_num_rn > 0 { + reference.borrow_mut().neighbor_back_rn = back_neighbors_rn; + } + else { + reference.borrow_mut().neighbor_back_rn = vec![None]; + } + + // right face of the volume + let mut front_neighbors_rn = vec![]; + let mut front_elements_num_rn = 0; + if y_min_pos != 0{ + for x in 0..reference.borrow().size_x { + for z in 0..reference.borrow().size_z { + if let Some(c) = neighbors.get_element(reference.borrow().position.x + x, y_min_pos, reference.borrow().position.z + z) { + front_elements_num_rn += 1; + front_neighbors_rn.push(Some(c.clone())); + } + else { + front_neighbors_rn.push(None); + } + } + } + } + if front_elements_num_rn > 0 { + reference.borrow_mut().neighbor_front_rn = front_neighbors_rn; + } + else { + reference.borrow_mut().neighbor_front_rn = vec![None]; + } + + // front face of the volume + let mut front_neighbors = vec![]; + let mut front_elements_num = 0; + if x_min_pos != 0 { + for y in 0..reference.borrow().size_y { + for z in 0..reference.borrow().size_z { + if let Some(c) = neighbors.get_element(x_min_pos, reference.borrow().position.y + y, reference.borrow().position.z + z) { + front_elements_num += 1; + front_neighbors.push(Some(c.clone())); + } + else { + front_neighbors.push(None); + } + } + } + } + if front_elements_num > 0 { + reference.borrow_mut().neighbor_front = front_neighbors; + } + else { + reference.borrow_mut().neighbor_front = vec![None]; + } + + // back face of the volume + let mut back_neighbors = vec![]; + let mut back_elements_num = 0; + for y in 0..reference.borrow().size_y { + for z in 0..reference.borrow().size_z { + if let Some(c) = neighbors.get_element(x_max_pos, reference.borrow().position.y + y, reference.borrow().position.z + z) { + back_elements_num += 1; + back_neighbors.push(Some(c.clone())); + } + else { + back_neighbors.push(None); + } + } + } + if back_elements_num > 0 { + reference.borrow_mut().neighbor_back = back_neighbors; + } + else { + reference.borrow_mut().neighbor_back = vec![None]; + } + } + println!("volume creation took {} s", start_time.elapsed().as_millis() as f32 / 1000.0); + (volumes, neighbors) + } + + fn to_quads(&self) -> Vec { + let mut quads = vec![]; + let float_pos = Vector3 {x: self.position.x as f32, y: self.position.y as f32, z: self.position.z as f32}; + //bottom sides of the volumes, top side of the block + for x in 0..self.size_x { + for y in 0..self.size_y { + let index = x * self.size_y + y; + if self.color_bottom.len() == 0 { + continue; + } + if self.neighbor_bottom.len() > index { + if let Some(_) = self.neighbor_bottom[index] { + continue; + } + } + let quad = Quad { + pos1: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + y as f32, z: -0.5 }, + pos4: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + y as f32, z: -0.5 }, + pos3: float_pos + Vector3 { x: 0.5 + x as f32, y: 0.5 + y as f32, z: -0.5 }, + pos2: float_pos + Vector3 { x: -0.5 + x as f32, y: 0.5 + y as f32, z: -0.5 }, + raster_pos: cgmath::Vector2 { x: x as u32, y: y as u32 }, + volume_index: 0 + }; + quads.push(quad); + } + } + //top sides of the volumes, bottom side of the block + for x in 0..self.size_x { + for y in 0..self.size_y { + let index = x * self.size_y + y; + if self.color_top.len() == 0 { + continue; + } + if self.neighbor_top.len() > index { + if let Some(_) = self.neighbor_top[index] { + continue; + } + } + let quad = Quad { + pos4: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + y as f32, z: self.size_z as f32 - 0.5 }, + pos1: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + y as f32, z: self.size_z as f32 - 0.5 }, + pos2: float_pos + Vector3 { x: 0.5 + x as f32, y: 0.5 + y as f32, z: self.size_z as f32 - 0.5 }, + pos3: float_pos + Vector3 { x: -0.5 + x as f32, y: 0.5 + y as f32, z: self.size_z as f32 - 0.5 }, + raster_pos: cgmath::Vector2 { x: x as u32, y: y as u32 }, + volume_index: 0 + }; + quads.push(quad); + } + } + + //front sides of the volumes, back side of the block + for x in 0..self.size_x { + for z in 0..self.size_z { + let index = x * self.size_z + z; + if self.color_front_rn.len() == 0 { + continue; + } + if self.neighbor_front_rn.len() > index { + if let Some(_) = self.neighbor_front_rn[index] { + continue; + } + } + let quad = Quad { + pos1: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + 0 as f32, z: z as f32 - 0.5 }, + pos4: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + 0 as f32, z: z as f32 + 0.5 }, + pos3: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + 0 as f32, z: z as f32 + 0.5 }, + pos2: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + 0 as f32, z: z as f32 - 0.5 }, + raster_pos: cgmath::Vector2 { x: x as u32, y: z as u32 }, + volume_index: 0 + }; + quads.push(quad); + } + } + + //back sides of the volumes, front side of the block + for x in 0..self.size_x { + for z in 0..self.size_z { + let index = x * self.size_z + z; + if self.color_back_rn.len() == 0 { + continue; + } + if self.neighbor_back_rn.len() > index { + if let Some(_) = self.neighbor_back_rn[index] { + continue; + } + } + let quad = Quad { + pos4: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + self.size_y as f32, z: z as f32 - 0.5 }, + pos1: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + self.size_y as f32, z: z as f32 + 0.5 }, + pos2: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + self.size_y as f32, z: z as f32 + 0.5 }, + pos3: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + self.size_y as f32, z: z as f32 - 0.5 }, + raster_pos: cgmath::Vector2 { x: x as u32, y: z as u32 }, + volume_index: 0 + }; + quads.push(quad); + } + } + quads } } diff --git a/src/vertex.rs b/src/vertex.rs index a94ddec..1d221de 100644 --- a/src/vertex.rs +++ b/src/vertex.rs @@ -161,4 +161,73 @@ impl Hash for SizedVertex { self.tex_coord[0].to_bits().hash(state); self.tex_coord[1].to_bits().hash(state); } -} \ No newline at end of file +} + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct RTVertex { + pub pos: Vec3, + pub raster_pos: cgmath::Vector2, + pub volume_start: u32, +} + +impl RTVertex { + pub const fn new(pos: Vec3, raster_pos: cgmath::Vector2, volume_start: u32) -> Self { + Self { pos, raster_pos, volume_start } + } +} +impl VertexContainer<3> for RTVertex { + fn binding_description() -> vk::VertexInputBindingDescription { + vk::VertexInputBindingDescription::builder() + .binding(0) + .stride(size_of::() as u32) + .input_rate(vk::VertexInputRate::VERTEX) + .build() + } + + fn attribute_descriptions() -> [vk::VertexInputAttributeDescription; 3] { + let pos = vk::VertexInputAttributeDescription::builder() + .binding(0) + .location(0) + .format(vk::Format::R32G32B32_SFLOAT) + .offset(0) + .build(); + + let raster_pos = vk::VertexInputAttributeDescription::builder() + .binding(0) + .location(1) + .format(vk::Format::R32G32_UINT) + .offset(size_of::() as u32) + .build(); + + let volume_start = vk::VertexInputAttributeDescription::builder() + .binding(0) + .location(2) + .format(vk::Format::R32_UINT) + .offset((size_of::() + size_of::>()) as u32) + .build(); + [pos, raster_pos, volume_start] + } +} + + +impl PartialEq for RTVertex { + fn eq(&self, other: &Self) -> bool { + self.pos == other.pos + && self.raster_pos == other.raster_pos + && self.volume_start == other.volume_start + } +} + +impl Eq for RTVertex {} + +impl Hash for RTVertex { + fn hash(&self, state: &mut H) { + self.pos[0].to_bits().hash(state); + self.pos[1].to_bits().hash(state); + self.pos[2].to_bits().hash(state); + self.raster_pos[0].hash(state); + self.raster_pos[1].hash(state); + self.volume_start.hash(state); + } +}