Terrain !
This commit is contained in:
+197
-62
@@ -4,6 +4,7 @@ use core::sync;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::hash::Hash;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
@@ -13,6 +14,8 @@ use bytemuck::Pod;
|
||||
use bytemuck::Zeroable;
|
||||
use crevice::std140::AsStd140;
|
||||
use crevice::std430::AsStd430;
|
||||
use egui::Color32;
|
||||
use egui::Label;
|
||||
use egui::emath::fast_midpoint;
|
||||
use egui::mutex::Mutex;
|
||||
use egui_plot::BarChart;
|
||||
@@ -21,6 +24,9 @@ use glam::Vec3;
|
||||
use glam::Vec4;
|
||||
use itertools::Itertools;
|
||||
use rand::random;
|
||||
use rayon::iter::IndexedParallelIterator;
|
||||
use rayon::iter::IntoParallelRefIterator;
|
||||
use rayon::iter::ParallelIterator;
|
||||
use wgpu::BindGroup;
|
||||
use wgpu::BindGroupEntry;
|
||||
use wgpu::BindGroupLayoutDescriptor;
|
||||
@@ -54,6 +60,7 @@ use wgpu::util::DownloadBuffer;
|
||||
use wgpu::util::StagingBelt;
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::event::DeviceEvent;
|
||||
use winit::event::MouseScrollDelta;
|
||||
use winit::event::WindowEvent;
|
||||
use winit::event_loop;
|
||||
use winit::event_loop::ActiveEventLoop;
|
||||
@@ -66,9 +73,14 @@ use winit::window::WindowId;
|
||||
|
||||
use crate::camera::Camera;
|
||||
use crate::egui_renderer::EguiRenderer;
|
||||
use crate::producers::BallGenerator;
|
||||
use crate::producers::ChunkedProducer;
|
||||
use crate::producers::Producer;
|
||||
use crate::producers::SineGenerator;
|
||||
use crate::producers::TerrainGenerator;
|
||||
use crate::voxel::cache::CacheNodeRequest;
|
||||
use crate::voxel::cache::CacheResponse;
|
||||
use crate::voxel::cache::ColorBytes;
|
||||
use crate::voxel::cache::DestinationElement;
|
||||
use crate::voxel::cache::LocationPoolElement;
|
||||
use crate::voxel::cache::RequestBuffer;
|
||||
@@ -103,6 +115,10 @@ struct State
|
||||
|
||||
pipeline: RenderPipeline,
|
||||
voxel_cache: Arc<Mutex<VoxelCache<4>>>,
|
||||
terrain_generator: Arc<TerrainGenerator<4>>,
|
||||
chunk_pos_map: Arc<HashMap<u32, (usize, usize, usize)>>,
|
||||
instance_buffer: Buffer,
|
||||
instance_count: usize,
|
||||
usage_vec: Arc<Mutex<Vec<usize>>>,
|
||||
insertion_debounce: bool,
|
||||
|
||||
@@ -123,6 +139,16 @@ struct Immediates
|
||||
frame_timestamp: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
|
||||
#[repr(C)]
|
||||
struct InstanceAttribute
|
||||
{
|
||||
x: f32,
|
||||
y: f32,
|
||||
z: f32,
|
||||
id: u32,
|
||||
}
|
||||
|
||||
impl State
|
||||
{
|
||||
async fn new(display: OwnedDisplayHandle, window: Arc<Window>) -> State
|
||||
@@ -141,7 +167,7 @@ impl State
|
||||
.unwrap();
|
||||
let (device, queue) = adapter
|
||||
.request_device(&wgpu::DeviceDescriptor {
|
||||
required_features: Features::IMMEDIATES,
|
||||
required_features: Features::IMMEDIATES | Features::SHADER_EARLY_DEPTH_TEST,
|
||||
required_limits: wgpu::Limits {
|
||||
max_immediate_size: 112,
|
||||
max_storage_buffers_per_shader_stage: 16,
|
||||
@@ -160,9 +186,34 @@ impl State
|
||||
|
||||
let egui_renderer = EguiRenderer::new(&device, surface_format, &window);
|
||||
|
||||
let mut voxel_cache = VoxelCache::<4>::new(16000, device.clone(), queue.clone());
|
||||
let id = voxel_cache.structure_table.allocate_structure(true);
|
||||
println!("id: {id}");
|
||||
let mut voxel_cache = VoxelCache::<4>::new(100_000, device.clone(), queue.clone());
|
||||
|
||||
let terrain_generator = TerrainGenerator::<4>::new(5, "vxls_height.tif", 0.2, "img.jpg");
|
||||
|
||||
let mut chunk_pos_map = HashMap::new();
|
||||
let chunk_instances = (0..terrain_generator.chunk_width)
|
||||
.cartesian_product(0..terrain_generator.chunk_height)
|
||||
.cartesian_product(0..terrain_generator.chunk_alt)
|
||||
.map(|((x, z), y)| {
|
||||
let chunk_id = voxel_cache.structure_table.allocate_structure(true);
|
||||
//dbg!(chunk_id);
|
||||
|
||||
chunk_pos_map.insert(chunk_id, (x, y, z));
|
||||
InstanceAttribute {
|
||||
x: x as f32,
|
||||
y: y as f32,
|
||||
z: z as f32,
|
||||
id: chunk_id,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let instance_count = chunk_instances.len();
|
||||
|
||||
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Instance buffer"),
|
||||
contents: bytemuck::cast_slice(chunk_instances.as_slice()),
|
||||
usage: BufferUsages::COPY_DST | BufferUsages::VERTEX,
|
||||
});
|
||||
|
||||
let shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: Some("Main shader module"),
|
||||
@@ -187,13 +238,28 @@ impl State
|
||||
module: &shader_module,
|
||||
entry_point: Some("chunk"),
|
||||
compilation_options: Default::default(),
|
||||
buffers: &[],
|
||||
buffers: &[Some(wgpu::VertexBufferLayout {
|
||||
array_stride: (size_of::<f32>() * 3 + size_of::<u32>()) as u64,
|
||||
step_mode: wgpu::VertexStepMode::Instance,
|
||||
attributes: &[
|
||||
wgpu::VertexAttribute {
|
||||
format: wgpu::VertexFormat::Float32x3,
|
||||
offset: 0,
|
||||
shader_location: 0,
|
||||
},
|
||||
wgpu::VertexAttribute {
|
||||
format: wgpu::VertexFormat::Uint32,
|
||||
offset: (size_of::<f32>() * 3) as u64,
|
||||
shader_location: 1,
|
||||
},
|
||||
],
|
||||
})],
|
||||
},
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
strip_index_format: None,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: None,
|
||||
cull_mode: Some(wgpu::Face::Front),
|
||||
unclipped_depth: false,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
conservative: false,
|
||||
@@ -201,7 +267,7 @@ impl State
|
||||
depth_stencil: Some(wgpu::DepthStencilState {
|
||||
format: wgpu::TextureFormat::Depth24PlusStencil8,
|
||||
depth_write_enabled: Some(true),
|
||||
depth_compare: Some(wgpu::CompareFunction::LessEqual),
|
||||
depth_compare: Some(wgpu::CompareFunction::Less),
|
||||
stencil: wgpu::StencilState::default(),
|
||||
bias: wgpu::DepthBiasState::default(),
|
||||
}),
|
||||
@@ -235,6 +301,10 @@ impl State
|
||||
voxel_cache: Arc::new(Mutex::new(voxel_cache)),
|
||||
insertion_debounce: false,
|
||||
camera: Default::default(),
|
||||
instance_buffer,
|
||||
instance_count,
|
||||
terrain_generator: Arc::new(terrain_generator),
|
||||
chunk_pos_map: chunk_pos_map.into(),
|
||||
};
|
||||
|
||||
// Configure surface for the first time
|
||||
@@ -323,9 +393,7 @@ impl State
|
||||
fn render(&mut self)
|
||||
{
|
||||
self.camera.update();
|
||||
|
||||
// Write random shit in request buffer
|
||||
let mut belt = StagingBelt::new(self.device.clone(), size_of::<u32>() as u64);
|
||||
self.voxel_cache.lock().next_frame();
|
||||
|
||||
// Create texture view.
|
||||
// NOTE: We must handle Timeout because the surface may be unavailable
|
||||
@@ -395,6 +463,7 @@ impl State
|
||||
});
|
||||
|
||||
renderpass.set_pipeline(&self.pipeline);
|
||||
renderpass.set_vertex_buffer(0, self.instance_buffer.slice(..));
|
||||
renderpass.set_bind_group(0, Some(&self.voxel_cache.lock().bind_group()), &[]);
|
||||
let imm = [Immediates {
|
||||
view_proj: self.camera.view_proj(),
|
||||
@@ -402,7 +471,7 @@ impl State
|
||||
frame_timestamp: self.voxel_cache.lock().current_timestamp(),
|
||||
}];
|
||||
renderpass.set_immediates(0, unsafe { as_raw_bytes(&imm) });
|
||||
renderpass.draw(0..36, 0..1);
|
||||
renderpass.draw(0..36, 0..(self.instance_count as u32));
|
||||
|
||||
// End the renderpass.
|
||||
drop(renderpass);
|
||||
@@ -410,14 +479,20 @@ impl State
|
||||
|
||||
let requests = self.device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("dummy_dumb_dinky_aaaahhh_buffer"),
|
||||
size: 16 * 256,
|
||||
size: 16 * 1024,
|
||||
usage: BufferUsages::STORAGE | BufferUsages::COPY_SRC,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
self.voxel_cache
|
||||
.lock()
|
||||
.cache_post_render(&mut encoder, requests.clone());
|
||||
if !self
|
||||
.camera
|
||||
.pressed_keyset
|
||||
.contains(&winit::keyboard::KeyCode::KeyF)
|
||||
{
|
||||
self.voxel_cache
|
||||
.lock()
|
||||
.cache_post_render(&mut encoder, requests.clone());
|
||||
}
|
||||
|
||||
// If you wanted to call any drawing commands, they would go here.
|
||||
{
|
||||
@@ -425,6 +500,17 @@ impl State
|
||||
egui::Window::new("Window ! ").resizable(true).show(
|
||||
self.egui_renderer.context(),
|
||||
|ui| {
|
||||
if self
|
||||
.camera
|
||||
.pressed_keyset
|
||||
.contains(&winit::keyboard::KeyCode::KeyF)
|
||||
{
|
||||
ui.label(
|
||||
egui::RichText::new("Cache paused")
|
||||
.color(Color32::RED)
|
||||
.size(28.),
|
||||
);
|
||||
}
|
||||
egui_plot::Plot::new("Plot").show(ui, |plot_ui| {
|
||||
plot_ui.bar_chart(BarChart::new(
|
||||
"histo",
|
||||
@@ -488,17 +574,24 @@ impl State
|
||||
self.insertion_debounce = false;
|
||||
}
|
||||
|
||||
if (self
|
||||
// if (self
|
||||
// .camera
|
||||
// .pressed_keyset
|
||||
// .contains(&winit::keyboard::KeyCode::KeyF))
|
||||
// && !self.insertion_debounce
|
||||
// {
|
||||
if !self
|
||||
.camera
|
||||
.pressed_keyset
|
||||
.contains(&winit::keyboard::KeyCode::KeyF))
|
||||
&& !self.insertion_debounce
|
||||
.contains(&winit::keyboard::KeyCode::KeyF)
|
||||
{
|
||||
self.insertion_debounce = true;
|
||||
let request_count = self.voxel_cache.lock().total_request_count();
|
||||
let cloned_cache = self.voxel_cache.clone();
|
||||
let cloned_device = self.device.clone();
|
||||
let cloned_queue = self.queue.clone();
|
||||
let cloned_generator = self.terrain_generator.clone();
|
||||
let cloned_map = self.chunk_pos_map.clone();
|
||||
let (tx, rx) = sync_channel(1);
|
||||
DownloadBuffer::read_buffer(
|
||||
&self.device.clone(),
|
||||
@@ -513,58 +606,88 @@ impl State
|
||||
let cache_node_requests: Vec<CacheNodeRequest> =
|
||||
bytemuck::pod_collect_to_vec(&buffer.unwrap());
|
||||
|
||||
let mut sine_gen = SineGenerator::<4>::new(4);
|
||||
let generator = cloned_generator;
|
||||
let gen_test = SineGenerator::<4>::new(5);
|
||||
|
||||
let mut structure_nodes = vec![];
|
||||
let mut color_nodes = vec![];
|
||||
let mut color_nodes: Vec<[ColorBytes; 64]> = vec![];
|
||||
let mut location_nodes = vec![];
|
||||
let mut destinations = vec![];
|
||||
for request in cache_node_requests.iter().take(request_count as usize)
|
||||
{
|
||||
let location;
|
||||
let node;
|
||||
if request.child_index == u32::MAX
|
||||
{
|
||||
// Produce root node
|
||||
node = sine_gen.produce_node(0, 0, 0, 0);
|
||||
location = LocationPoolElement {
|
||||
structure_id: 0,
|
||||
structure_locator: NTreeNodeLocator::<4>::root().as_usize() as u32,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
// Figure out depth of request
|
||||
let locator = NTreeNodeLocator::<4>::from_usize(
|
||||
request.structure_locator as usize,
|
||||
);
|
||||
let depth = locator.depth();
|
||||
//let (x, y, z) = locator.node_location();
|
||||
|
||||
let child_x = request.child_index / (4 * 4);
|
||||
let child_y = (request.child_index % (4 * 4)) / 4;
|
||||
let child_z = request.child_index % 4;
|
||||
cache_node_requests
|
||||
.par_iter()
|
||||
.take(request_count as usize)
|
||||
.map(|request| {
|
||||
// Unpack structure id
|
||||
let (chunk_x, chunk_y, chunk_z) =
|
||||
*cloned_map.get(&request.structure_id).unwrap();
|
||||
|
||||
let child_locator =
|
||||
locator.child(child_x as usize, child_y as usize, child_z as usize);
|
||||
let location;
|
||||
let node;
|
||||
if request.child_index == u32::MAX
|
||||
{
|
||||
// Produce root node
|
||||
node =
|
||||
generator.produce_node(0, 0, 0, 0, (chunk_x, chunk_y, chunk_z));
|
||||
location = LocationPoolElement {
|
||||
structure_id: request.structure_id,
|
||||
structure_locator: NTreeNodeLocator::<4>::root().as_usize()
|
||||
as u32,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
// Figure out depth of request
|
||||
let locator = NTreeNodeLocator::<4>::from_usize(
|
||||
request.structure_locator as usize,
|
||||
);
|
||||
let depth = locator.depth();
|
||||
//let (x, y, z) = locator.node_location();
|
||||
|
||||
let (nx, ny, nz) = child_locator.node_location();
|
||||
let child_z = request.child_index / (4 * 4);
|
||||
let child_y = (request.child_index % (4 * 4)) / 4;
|
||||
let child_x = request.child_index % 4;
|
||||
|
||||
node = sine_gen.produce_node(depth + 1, nx, ny, nz);
|
||||
let child_locator = locator.child(
|
||||
child_x as usize,
|
||||
child_y as usize,
|
||||
child_z as usize,
|
||||
);
|
||||
|
||||
location = LocationPoolElement {
|
||||
structure_id: 0,
|
||||
structure_locator: child_locator.as_usize() as u32,
|
||||
};
|
||||
}
|
||||
let (nx, ny, nz) = child_locator.node_location();
|
||||
|
||||
structure_nodes.push(node.structure);
|
||||
color_nodes.push(node.colors);
|
||||
location_nodes.push(location);
|
||||
destinations.push(DestinationElement {
|
||||
node: request.node_index,
|
||||
child: request.child_index,
|
||||
node = generator.produce_node(
|
||||
depth + 1,
|
||||
nx,
|
||||
ny,
|
||||
nz,
|
||||
(chunk_x, chunk_y, chunk_z),
|
||||
);
|
||||
|
||||
location = LocationPoolElement {
|
||||
structure_id: request.structure_id,
|
||||
structure_locator: child_locator.as_usize() as u32,
|
||||
};
|
||||
}
|
||||
|
||||
(
|
||||
node.structure,
|
||||
node.colors,
|
||||
location,
|
||||
DestinationElement {
|
||||
node: request.node_index,
|
||||
child: request.child_index,
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.for_each(|data| {
|
||||
structure_nodes.push(data.0);
|
||||
color_nodes.push(std::array::from_fn(|i| data.1[i].into()));
|
||||
location_nodes.push(data.2);
|
||||
destinations.push(data.3);
|
||||
});
|
||||
}
|
||||
|
||||
if structure_nodes.len() != 0
|
||||
{
|
||||
@@ -607,7 +730,7 @@ impl State
|
||||
}
|
||||
},
|
||||
);
|
||||
println!("Total request count: {}", request_count);
|
||||
//println!("Total request count: {}", request_count);
|
||||
loop
|
||||
{
|
||||
if rx.try_recv().is_ok()
|
||||
@@ -617,10 +740,17 @@ impl State
|
||||
let _ = self.device.poll(wgpu::wgt::PollType::Poll);
|
||||
}
|
||||
|
||||
self.voxel_cache.lock().next_frame();
|
||||
drop(rx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mouse_wheel(&mut self, delta: MouseScrollDelta)
|
||||
{
|
||||
if let MouseScrollDelta::LineDelta(_, y) = delta
|
||||
{
|
||||
self.camera.speed += y * (self.camera.speed * 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -679,6 +809,11 @@ impl ApplicationHandler for App
|
||||
// here as this event is always followed up by redraw request.
|
||||
state.resize(size);
|
||||
}
|
||||
WindowEvent::MouseWheel { delta, .. } =>
|
||||
{
|
||||
state.mouse_wheel(delta);
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user