mod oct_tree; mod empty_volume; mod light; mod memorizable; use anyhow::Ok; use light::{DirectionalLight, LightSource}; use vulkanalia::prelude::v1_0::*; use anyhow::Result; use cgmath::{vec2, vec3, Vector3}; use std::cell::RefCell; use std::rc::Rc; use crate::scene::memorizable::Memorizable; 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::drawable::Drawable; use crate::scene::oct_tree::{OctTree, OctTreeIter, CHUNK_SIZE}; use crate::scene::empty_volume::EmptyVolume; use crate::scene::light::PointLight; extern crate rand; use rand::Rng; #[repr(C)] #[derive(Clone, Debug, Default)] pub struct Scene { pub vertices: Vec<vertex::Vertex>, pub sized_vertices: Vec<vertex::SizedVertex>, pub rt_vertices: Vec<vertex::RTVertex>, pub indices_cube: Vec<u32>, pub indices_cuboid: Vec<u32>, pub indices_rt: Vec<u32>, pub vertex_buffer_cube: vk::Buffer, pub vertex_buffer_memory_cube: vk::DeviceMemory, pub index_buffer_cube: vk::Buffer, pub index_buffer_memory_cube: vk::DeviceMemory, pub vertex_buffer_cuboid: vk::Buffer, pub vertex_buffer_memory_cuboid: vk::DeviceMemory, 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, pub rt_memory: Vec<u32>, point_lights: Vec<Rc<RefCell<PointLight>>>, directional_lights: Vec<Rc<RefCell<DirectionalLight>>>, } impl Scene { pub unsafe fn prepare_data(&mut self, instance: &vulkanalia::Instance, device: &vulkanalia::Device, data: &mut AppData) -> Result<()> { let mut rng = rand::thread_rng(); 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<Cube> = OctTree::create(CHUNK_SIZE)?; for x_index in 0..grid_size { for y_index in 0..grid_size { let shade = (rng.gen_range(0..50) as f32) / 100.0; let cube = Cube { pos: vec3(x_index as f32, y_index as f32, 5.0), color: vec3(shade, 1.0, shade), tex_coord: vec2(0.0, 0.0), transparent: false, roughness: 0, }; oct_tree.set_cube(cube.clone()); } } let shade = (rng.gen_range(0..25) as f32) / 100.0; let cube = Cube { pos: vec3(10.0, 10.0, 10.0), color: vec3(1.0, 0.0, 0.0), tex_coord: vec2(0.0, 0.0), transparent: true, roughness: 32, }; oct_tree.set_cube(cube.clone()); let cube = Cube { pos: vec3(10.0, 10.0, 9.0), color: vec3(1.0, 0.0, 0.0), tex_coord: vec2(0.0, 0.0), transparent: true, roughness: 32, }; oct_tree.set_cube(cube.clone()); self.point_lights.push(Rc::new(RefCell::new(PointLight { pos: vec3(11.0, 11.0, 11.0), color: vec3(1.0, 1.0, 1.0), memory_start: 0 }))); self.point_lights.push(Rc::new(RefCell::new(PointLight { pos: vec3(9.0, 9.0, 11.0), color: vec3(0.5, 0.5, 0.5), memory_start: 0 }))); self.directional_lights.push(Rc::new(RefCell::new(DirectionalLight { direction: vec3(1.0, 1.0, -1.0), color: vec3(0.1, 0.1, 0.1), memory_start: 0 }))); let empty_volumes: Vec<Rc<RefCell<EmptyVolume>>>; (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 { let sized_index = self.sized_vertices.len(); let index = self.vertices.len(); match item { Some(cube) => { /*if (cube.pos.x + cube.pos.y) as usize % 2 == 0{ /**/ let cuboid = Cuboid { pos: cube.pos, color: cube.color, tex_coord: cube.tex_coord, size: Vector3 {x: 1.0, y: 1.0, z: 1.0}, }; cuboid.draw(&data.topology, sized_index, self); } else { cube.draw(&data.topology, index, self); }*/ //cube.draw(&data.topology, index, self); } None => {} } } let cube = Cuboid { pos: vec3(11.0, 11.0, 11.0), color: vec3(1.0, 1.0, 1.0), tex_coord: vec2(0.0, 0.0), size: Vector3 {x: 0.5, y: 0.5, z: 0.5} }; let index = self.sized_vertices.len(); cube.draw(&data.topology, index, self); let cube = Cuboid { pos: vec3(9.0, 9.0, 11.0), color: vec3(1.0, 1.0, 1.0), tex_coord: vec2(0.0, 0.0), size: Vector3 {x: 0.5, y: 0.5, z: 0.5} }; let index = self.sized_vertices.len(); cube.draw(&data.topology, index, self); let mut memory_index = 6; // 0 - location for the maximum number of lights referenced per chunk (also will be the invalid memory allocation for pointing to a nonexistant neighbor) // 1 - location for the max iterations per light // 2 - diffuse raster samples (2*n + 1) * (2*n + 1) so as to always have at least the central fragment covered // 3 - diffuse raster size // 4 - max recursive rays // 5 - diffuse rays per hit for light in LightsIter::new(self) { light.borrow_mut().set_memory_start(memory_index); memory_index += light.borrow_mut().get_buffer_mem_size(data) as usize; } for volume in &empty_volumes { volume.borrow_mut().set_memory_start(memory_index); memory_index += volume.borrow().get_buffer_mem_size(data) as usize; } for volume in &empty_volumes { let quads = volume.borrow().to_quads(); for quad in quads { quad.draw(&data.topology, self.rt_vertices.len(), self); } } println!("Memory size is {} kB, max indes is {}", memory_index * 32 / 8 /1024 + 1, memory_index); let mut volume_vec = vec![data.num_lights_per_volume; memory_index]; volume_vec[1] = data.max_iterations_per_light; volume_vec[2] = data.diffuse_raster_steps; volume_vec[3] = u32::from_ne_bytes(data.diffuse_raster_size.to_ne_bytes()); volume_vec[4] = data.max_recursive_rays; volume_vec[5] = data.diffuse_rays_per_hit; for volume in &empty_volumes { volume_vec = volume.borrow().insert_into_memory(volume_vec, data, &self); } for light in LightsIter::new(self) { volume_vec = light.borrow().insert_into_memory(volume_vec, data, &self); } //println!("volume_vec print {:?}", volume_vec); self.rt_memory = volume_vec; data.scene_rt_memory_size = (self.rt_memory.len() * 4) as u64; // size of the needed buffer size in bytes if self.vertices.len() != 0 { (self.vertex_buffer_cube, self.vertex_buffer_memory_cube) = buffer::create_vertex_buffer(instance, device, &data, &self.vertices)?; (self.index_buffer_cube, self.index_buffer_memory_cube) = buffer::create_index_buffer(&instance, &device, &data, &self.indices_cube)?; } if self.sized_vertices.len() != 0 { (self.vertex_buffer_cuboid, self.vertex_buffer_memory_cuboid) = buffer::create_vertex_buffer(instance, device, &data, &self.sized_vertices)?; (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(()) } pub unsafe fn destroy(&mut self, device: &vulkanalia::Device) { device.destroy_buffer(self.index_buffer_cube, None); device.free_memory(self.index_buffer_memory_cube, None); device.destroy_buffer(self.vertex_buffer_cube, None); device.free_memory(self.vertex_buffer_memory_cube, None); device.destroy_buffer(self.index_buffer_cuboid, None); 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.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); } fn get_light_iter(&self) -> LightsIter { LightsIter::new(self) } } pub struct LightsIter<'a> { light_index: usize, scene: &'a Scene, } impl<'a> LightsIter<'a> { fn new(scene: &'a Scene) -> Self { LightsIter {light_index: 0, scene: scene} } } impl<'a> Iterator for LightsIter<'a> { type Item = Rc<RefCell<dyn LightSource>>; fn next(&mut self) -> Option<Self::Item> { if self.light_index >= self.scene.point_lights.len() { if self.light_index - self.scene.point_lights.len() >= self.scene.directional_lights.len() { None } else { let result = self.scene.directional_lights[self.light_index - self.scene.point_lights.len()].clone(); self.light_index += 1; Some(result) } } else { let result = self.scene.point_lights[self.light_index].clone(); self.light_index += 1; Some(result) } } }