Initial
This commit is contained in:
+692
-2
@@ -1,3 +1,693 @@
|
||||
fn main() -> anyhow::Result<()> {
|
||||
wgpu_template::run()
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
use core::sync;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::mpsc::sync_channel;
|
||||
|
||||
use bytemuck::Pod;
|
||||
use bytemuck::Zeroable;
|
||||
use crevice::std140::AsStd140;
|
||||
use crevice::std430::AsStd430;
|
||||
use egui::emath::fast_midpoint;
|
||||
use egui::mutex::Mutex;
|
||||
use glam::Mat4;
|
||||
use glam::Vec3;
|
||||
use glam::Vec4;
|
||||
use itertools::Itertools;
|
||||
use rand::random;
|
||||
use wgpu::BindGroup;
|
||||
use wgpu::BindGroupEntry;
|
||||
use wgpu::BindGroupLayoutDescriptor;
|
||||
use wgpu::BindGroupLayoutEntry;
|
||||
use wgpu::Buffer;
|
||||
use wgpu::BufferUsages;
|
||||
use wgpu::DepthBiasState;
|
||||
use wgpu::Device;
|
||||
use wgpu::Extent3d;
|
||||
use wgpu::Features;
|
||||
use wgpu::FragmentState;
|
||||
use wgpu::InstanceDescriptor;
|
||||
use wgpu::InstanceFlags;
|
||||
use wgpu::MemoryBudgetThresholds;
|
||||
use wgpu::NoopBackendOptions;
|
||||
use wgpu::Operations;
|
||||
use wgpu::PrimitiveState;
|
||||
use wgpu::RenderPassDepthStencilAttachment;
|
||||
use wgpu::RenderPipeline;
|
||||
use wgpu::RenderPipelineDescriptor;
|
||||
use wgpu::ShaderModuleDescriptor;
|
||||
use wgpu::ShaderStages;
|
||||
use wgpu::StencilState;
|
||||
use wgpu::Texture;
|
||||
use wgpu::TextureUsages;
|
||||
use wgpu::TextureView;
|
||||
use wgpu::VertexState;
|
||||
use wgpu::util::BufferInitDescriptor;
|
||||
use wgpu::util::DeviceExt;
|
||||
use wgpu::util::DownloadBuffer;
|
||||
use wgpu::util::StagingBelt;
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::event::DeviceEvent;
|
||||
use winit::event::WindowEvent;
|
||||
use winit::event_loop;
|
||||
use winit::event_loop::ActiveEventLoop;
|
||||
use winit::event_loop::ControlFlow;
|
||||
use winit::event_loop::EventLoop;
|
||||
use winit::event_loop::OwnedDisplayHandle;
|
||||
use winit::platform::x11::EventLoopBuilderExtX11;
|
||||
use winit::window::Window;
|
||||
use winit::window::WindowId;
|
||||
|
||||
use crate::camera::Camera;
|
||||
use crate::egui_renderer::EguiRenderer;
|
||||
use crate::producers::SineGenerator;
|
||||
use crate::voxel::cache::CacheNodeRequest;
|
||||
use crate::voxel::cache::CacheResponse;
|
||||
use crate::voxel::cache::DestinationElement;
|
||||
use crate::voxel::cache::LocationPoolElement;
|
||||
use crate::voxel::cache::RequestBuffer;
|
||||
use crate::voxel::cache::UsageBuffer;
|
||||
use crate::voxel::cache::VoxelCache;
|
||||
use crate::voxel::gpu::ExplicitNTreeNode;
|
||||
use crate::voxel::pipeline::ChunkHandle;
|
||||
use crate::voxel::pipeline::ChunkObject;
|
||||
use crate::voxel::pipeline::VoxelPipeline;
|
||||
use crate::voxel::sparse::Color;
|
||||
use crate::voxel::sparse::NTree;
|
||||
use crate::voxel::sparse::NTreeNodeLocator;
|
||||
|
||||
mod camera;
|
||||
mod egui_renderer;
|
||||
mod producers;
|
||||
mod voxel;
|
||||
//mod tree;
|
||||
//
|
||||
|
||||
struct State
|
||||
{
|
||||
instance: wgpu::Instance,
|
||||
window: Arc<Window>,
|
||||
device: wgpu::Device,
|
||||
queue: wgpu::Queue,
|
||||
size: winit::dpi::PhysicalSize<u32>,
|
||||
surface: wgpu::Surface<'static>,
|
||||
depth_buffer: (wgpu::Texture, wgpu::TextureView),
|
||||
surface_format: wgpu::TextureFormat,
|
||||
egui_renderer: EguiRenderer,
|
||||
|
||||
pipeline: RenderPipeline,
|
||||
voxel_cache: Arc<Mutex<VoxelCache<4>>>,
|
||||
insertion_debounce: bool,
|
||||
|
||||
camera: Camera,
|
||||
}
|
||||
|
||||
pub unsafe fn as_raw_bytes<T: Sized>(slice: &[T]) -> &[u8]
|
||||
{
|
||||
let size = slice.len() * size_of::<T>();
|
||||
unsafe { std::slice::from_raw_parts(slice.as_ptr() as *const u8, size) }
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Immediates
|
||||
{
|
||||
view_proj: Mat4,
|
||||
cam_pos: Vec3,
|
||||
frame_timestamp: u32,
|
||||
}
|
||||
|
||||
impl State
|
||||
{
|
||||
async fn new(display: OwnedDisplayHandle, window: Arc<Window>) -> State
|
||||
{
|
||||
let instance = wgpu::Instance::new(InstanceDescriptor {
|
||||
backends: wgpu::Backends::VULKAN,
|
||||
display: Some(Box::new(display)),
|
||||
|
||||
flags: InstanceFlags::default(),
|
||||
memory_budget_thresholds: MemoryBudgetThresholds::default(),
|
||||
backend_options: Default::default(),
|
||||
});
|
||||
let adapter = instance
|
||||
.request_adapter(&wgpu::RequestAdapterOptions::default())
|
||||
.await
|
||||
.unwrap();
|
||||
let (device, queue) = adapter
|
||||
.request_device(&wgpu::DeviceDescriptor {
|
||||
required_features: Features::IMMEDIATES,
|
||||
required_limits: wgpu::Limits {
|
||||
max_immediate_size: 112,
|
||||
max_storage_buffers_per_shader_stage: 16,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let size = window.inner_size();
|
||||
|
||||
let surface = instance.create_surface(window.clone()).unwrap();
|
||||
let cap = surface.get_capabilities(&adapter);
|
||||
let surface_format = cap.formats[0];
|
||||
|
||||
let egui_renderer = EguiRenderer::new(&device, surface_format, &window);
|
||||
|
||||
let mut voxel_cache = VoxelCache::<4>::new(4096, device.clone(), queue.clone());
|
||||
let id = voxel_cache.structure_table.allocate_structure(true);
|
||||
println!("id: {id}");
|
||||
|
||||
let shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: Some("Main shader module"),
|
||||
source: wgpu::ShaderSource::Wgsl(
|
||||
std::fs::read_to_string("shaders/voxel.wgsl")
|
||||
.unwrap()
|
||||
.into(),
|
||||
),
|
||||
});
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Voxel pipeline layout"),
|
||||
|
||||
bind_group_layouts: &[Some(&voxel_cache.bind_group_layout())],
|
||||
immediate_size: size_of::<Immediates>() as u32,
|
||||
});
|
||||
|
||||
let chunk_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Render pipeline"),
|
||||
layout: Some(&pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader_module,
|
||||
entry_point: Some("chunk"),
|
||||
compilation_options: Default::default(),
|
||||
buffers: &[],
|
||||
},
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
strip_index_format: None,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: None,
|
||||
unclipped_depth: false,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
conservative: false,
|
||||
},
|
||||
depth_stencil: Some(wgpu::DepthStencilState {
|
||||
format: wgpu::TextureFormat::Depth24PlusStencil8,
|
||||
depth_write_enabled: Some(true),
|
||||
depth_compare: Some(wgpu::CompareFunction::LessEqual),
|
||||
stencil: wgpu::StencilState::default(),
|
||||
bias: wgpu::DepthBiasState::default(),
|
||||
}),
|
||||
multisample: wgpu::MultisampleState::default(),
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader_module,
|
||||
entry_point: Some("fragment"),
|
||||
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||
targets: &[Some(wgpu::ColorTargetState {
|
||||
format: surface_format,
|
||||
blend: None,
|
||||
write_mask: wgpu::ColorWrites::default(),
|
||||
})],
|
||||
}),
|
||||
multiview_mask: None,
|
||||
cache: None,
|
||||
});
|
||||
|
||||
let state = State {
|
||||
instance,
|
||||
window,
|
||||
size,
|
||||
surface,
|
||||
surface_format,
|
||||
egui_renderer,
|
||||
depth_buffer: Self::create_depth_buffer(&device, size.width, size.height),
|
||||
queue,
|
||||
device,
|
||||
pipeline: chunk_pipeline,
|
||||
voxel_cache: Arc::new(Mutex::new(voxel_cache)),
|
||||
insertion_debounce: false,
|
||||
camera: Default::default(),
|
||||
};
|
||||
|
||||
// Configure surface for the first time
|
||||
state.configure_surface();
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
fn get_window(&self) -> &Window
|
||||
{
|
||||
&self.window
|
||||
}
|
||||
|
||||
fn handle_event(&mut self, event: &WindowEvent)
|
||||
{
|
||||
self.egui_renderer.handle_input(&self.window, event);
|
||||
self.camera.handle_input(event);
|
||||
}
|
||||
|
||||
fn handle_device_event(&mut self, event: &DeviceEvent)
|
||||
{
|
||||
#[allow(clippy::single_match)]
|
||||
match event
|
||||
{
|
||||
winit::event::DeviceEvent::MouseMotion { delta } =>
|
||||
{
|
||||
self.camera.cursor_moved(delta.0 as f32, delta.1 as f32);
|
||||
}
|
||||
|
||||
_ =>
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_depth_buffer(device: &Device, width: u32, height: u32) -> (Texture, TextureView)
|
||||
{
|
||||
let texture = device.create_texture(&wgpu::wgt::TextureDescriptor {
|
||||
label: Some("Depth buffer"),
|
||||
size: Extent3d {
|
||||
width,
|
||||
height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Depth24PlusStencil8,
|
||||
usage: TextureUsages::RENDER_ATTACHMENT,
|
||||
view_formats: &[wgpu::TextureFormat::Depth24PlusStencil8.add_srgb_suffix()],
|
||||
});
|
||||
let texture_view = texture.create_view(&wgpu::wgt::TextureViewDescriptor {
|
||||
label: Some("depth view"),
|
||||
..Default::default()
|
||||
});
|
||||
(texture, texture_view)
|
||||
}
|
||||
|
||||
fn configure_surface(&self)
|
||||
{
|
||||
let surface_config = wgpu::SurfaceConfiguration {
|
||||
color_space: wgpu::SurfaceColorSpace::Auto,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
format: self.surface_format,
|
||||
// Request compatibility with the sRGB-format texture view we‘re going to create later.
|
||||
view_formats: vec![self.surface_format.add_srgb_suffix()],
|
||||
alpha_mode: wgpu::CompositeAlphaMode::Auto,
|
||||
width: self.size.width,
|
||||
height: self.size.height,
|
||||
desired_maximum_frame_latency: 2,
|
||||
present_mode: wgpu::PresentMode::AutoVsync,
|
||||
};
|
||||
self.surface.configure(&self.device, &surface_config);
|
||||
}
|
||||
|
||||
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>)
|
||||
{
|
||||
self.size = new_size;
|
||||
self.camera.aspect = new_size.width as f32 / new_size.height as f32;
|
||||
|
||||
// reconfigure the surface
|
||||
self.configure_surface();
|
||||
self.depth_buffer =
|
||||
Self::create_depth_buffer(&self.device, new_size.width, new_size.height);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Create texture view.
|
||||
// NOTE: We must handle Timeout because the surface may be unavailable
|
||||
// (e.g., when the window is occluded on macOS).
|
||||
let surface_texture = match self.surface.get_current_texture()
|
||||
{
|
||||
wgpu::CurrentSurfaceTexture::Success(texture) => texture,
|
||||
wgpu::CurrentSurfaceTexture::Occluded | wgpu::CurrentSurfaceTexture::Timeout => return,
|
||||
wgpu::CurrentSurfaceTexture::Suboptimal(texture) =>
|
||||
{
|
||||
drop(texture);
|
||||
self.configure_surface();
|
||||
return;
|
||||
}
|
||||
wgpu::CurrentSurfaceTexture::Outdated =>
|
||||
{
|
||||
self.configure_surface();
|
||||
return;
|
||||
}
|
||||
wgpu::CurrentSurfaceTexture::Validation =>
|
||||
{
|
||||
unreachable!("No error scope registered, so validation errors will panic")
|
||||
}
|
||||
wgpu::CurrentSurfaceTexture::Lost =>
|
||||
{
|
||||
self.surface = self.instance.create_surface(self.window.clone()).unwrap();
|
||||
self.configure_surface();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let texture_view = surface_texture
|
||||
.texture
|
||||
.create_view(&wgpu::TextureViewDescriptor {
|
||||
// Without add_srgb_suffix() the image we will be working with
|
||||
// might not be "gamma correct".
|
||||
format: Some(self.surface_format.add_srgb_suffix()),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
// Renders a GREEN screen
|
||||
let mut encoder = self.device.create_command_encoder(&Default::default());
|
||||
|
||||
{
|
||||
let mut renderpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: None,
|
||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||
view: &texture_view,
|
||||
depth_slice: None,
|
||||
resolve_target: None,
|
||||
ops: wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
|
||||
store: wgpu::StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
|
||||
view: &self.depth_buffer.1,
|
||||
depth_ops: Some(Operations {
|
||||
load: wgpu::LoadOp::Clear(1.),
|
||||
store: wgpu::StoreOp::Discard,
|
||||
}),
|
||||
stencil_ops: None,
|
||||
}),
|
||||
timestamp_writes: None,
|
||||
occlusion_query_set: None,
|
||||
multiview_mask: None,
|
||||
});
|
||||
|
||||
renderpass.set_pipeline(&self.pipeline);
|
||||
renderpass.set_bind_group(0, Some(&self.voxel_cache.lock().bind_group()), &[]);
|
||||
let imm = [Immediates {
|
||||
view_proj: self.camera.view_proj(),
|
||||
cam_pos: self.camera.position,
|
||||
frame_timestamp: self.voxel_cache.lock().current_timestamp(),
|
||||
}];
|
||||
renderpass.set_immediates(0, unsafe { as_raw_bytes(&imm) });
|
||||
renderpass.draw(0..36, 0..1);
|
||||
|
||||
// End the renderpass.
|
||||
drop(renderpass);
|
||||
}
|
||||
|
||||
let requests = self.device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("dummy_dumb_dinky_aaaahhh_buffer"),
|
||||
size: 16 * 64,
|
||||
usage: BufferUsages::STORAGE | BufferUsages::COPY_SRC,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
self.voxel_cache
|
||||
.lock()
|
||||
.cache_post_render(&mut encoder, requests.clone());
|
||||
|
||||
// If you wanted to call any drawing commands, they would go here.
|
||||
{
|
||||
self.egui_renderer.begin_frame(&self.window);
|
||||
egui::Window::new("Window ! ")
|
||||
.resizable(true)
|
||||
.show(self.egui_renderer.context(), |ui| ui.label("Hello !"));
|
||||
|
||||
let screen_descriptor = egui_wgpu::ScreenDescriptor {
|
||||
size_in_pixels: [self.size.width, self.size.height],
|
||||
pixels_per_point: self.window.as_ref().scale_factor() as f32,
|
||||
};
|
||||
|
||||
self.egui_renderer.end_frame_and_draw(
|
||||
&self.device,
|
||||
&self.queue,
|
||||
&mut encoder,
|
||||
&self.window,
|
||||
&texture_view,
|
||||
screen_descriptor,
|
||||
);
|
||||
}
|
||||
|
||||
// Submit the command in the queue to execute
|
||||
self.queue.submit([encoder.finish()]);
|
||||
self.window.pre_present_notify();
|
||||
self.queue.present(surface_texture);
|
||||
if !self
|
||||
.camera
|
||||
.pressed_keyset
|
||||
.contains(&winit::keyboard::KeyCode::KeyF)
|
||||
{
|
||||
self.insertion_debounce = false;
|
||||
}
|
||||
|
||||
if (!self
|
||||
.camera
|
||||
.pressed_keyset
|
||||
.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 (tx, rx) = sync_channel(1);
|
||||
DownloadBuffer::read_buffer(
|
||||
&self.device.clone(),
|
||||
&self.queue.clone(),
|
||||
&requests.slice(0..),
|
||||
move |buffer| {
|
||||
if tx.try_send(()).is_err()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let cache_node_requests: Vec<CacheNodeRequest> =
|
||||
bytemuck::pod_collect_to_vec(&buffer.unwrap());
|
||||
|
||||
let mut sine_gen = SineGenerator::<4>::new(4);
|
||||
let mut structure_nodes = vec![];
|
||||
let mut color_nodes = 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;
|
||||
|
||||
let child_locator =
|
||||
locator.child(child_x as usize, child_y as usize, child_z as usize);
|
||||
|
||||
let (nx, ny, nz) = child_locator.node_location();
|
||||
|
||||
node = sine_gen.produce_node(depth + 1, nx, ny, nz);
|
||||
|
||||
location = LocationPoolElement {
|
||||
structure_id: 0,
|
||||
structure_locator: child_locator.as_usize() as u32,
|
||||
};
|
||||
}
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
if structure_nodes.len() != 0
|
||||
{
|
||||
let structre_node_buffer =
|
||||
cloned_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: unsafe { as_raw_bytes(structure_nodes.as_slice()) },
|
||||
usage: BufferUsages::STORAGE,
|
||||
});
|
||||
let color_node_buffer =
|
||||
cloned_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: unsafe { as_raw_bytes(color_nodes.as_slice()) },
|
||||
usage: BufferUsages::STORAGE,
|
||||
});
|
||||
let location_node_buffer =
|
||||
cloned_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: unsafe { as_raw_bytes(location_nodes.as_slice()) },
|
||||
usage: BufferUsages::STORAGE,
|
||||
});
|
||||
let destinations_buffer =
|
||||
cloned_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: unsafe { as_raw_bytes(destinations.as_slice()) },
|
||||
usage: BufferUsages::STORAGE,
|
||||
});
|
||||
|
||||
let mut encoder = cloned_device.create_command_encoder(&Default::default());
|
||||
cloned_cache.lock().cache_insert(
|
||||
&mut encoder,
|
||||
&CacheResponse {
|
||||
structure_nodes: structre_node_buffer,
|
||||
color_nodes: color_node_buffer,
|
||||
locations: location_node_buffer,
|
||||
parents: destinations_buffer,
|
||||
},
|
||||
);
|
||||
cloned_queue.submit([encoder.finish()]);
|
||||
}
|
||||
cloned_cache.lock().next_frame();
|
||||
},
|
||||
);
|
||||
println!("Total request count: {}", request_count);
|
||||
loop
|
||||
{
|
||||
if rx.try_recv().is_ok()
|
||||
{
|
||||
break;
|
||||
}
|
||||
let _ = self.device.poll(wgpu::wgt::PollType::Poll);
|
||||
}
|
||||
drop(rx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct App
|
||||
{
|
||||
state: Option<State>,
|
||||
}
|
||||
|
||||
impl ApplicationHandler for App
|
||||
{
|
||||
fn resumed(&mut self, event_loop: &ActiveEventLoop)
|
||||
{
|
||||
// Create window object
|
||||
let window = Arc::new(
|
||||
event_loop
|
||||
.create_window(Window::default_attributes())
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let state = pollster::block_on(State::new(
|
||||
event_loop.owned_display_handle(),
|
||||
window.clone(),
|
||||
));
|
||||
self.state = Some(state);
|
||||
|
||||
window.request_redraw();
|
||||
window.set_cursor_visible(false);
|
||||
// window
|
||||
// .set_cursor_grab(winit::window::CursorGrabMode::Locked)
|
||||
// .unwrap();
|
||||
let _ = window
|
||||
.set_cursor_grab(winit::window::CursorGrabMode::Locked)
|
||||
.or_else(|_| window.set_cursor_grab(winit::window::CursorGrabMode::Confined));
|
||||
}
|
||||
|
||||
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent)
|
||||
{
|
||||
let state = self.state.as_mut().unwrap();
|
||||
state.handle_event(&event);
|
||||
match event
|
||||
{
|
||||
WindowEvent::CloseRequested =>
|
||||
{
|
||||
println!("The close button was pressed; stopping");
|
||||
event_loop.exit();
|
||||
}
|
||||
WindowEvent::RedrawRequested =>
|
||||
{
|
||||
state.render();
|
||||
// Emits a new redraw requested event.
|
||||
state.get_window().request_redraw();
|
||||
}
|
||||
WindowEvent::Resized(size) =>
|
||||
{
|
||||
// Reconfigures the size of the surface. We do not re-render
|
||||
// here as this event is always followed up by redraw request.
|
||||
state.resize(size);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn device_event(
|
||||
&mut self,
|
||||
_event_loop: &event_loop::ActiveEventLoop,
|
||||
_device_id: winit::event::DeviceId,
|
||||
event: winit::event::DeviceEvent,
|
||||
)
|
||||
{
|
||||
let state = self.state.as_mut().unwrap();
|
||||
state.handle_device_event(&event);
|
||||
}
|
||||
}
|
||||
|
||||
fn main()
|
||||
{
|
||||
// wgpu uses `log` for all of our logging, so we initialize a logger with the `env_logger` crate.
|
||||
//
|
||||
// To change the log level, set the `RUST_LOG` environment variable. See the `env_logger`
|
||||
// documentation for more information.
|
||||
env_logger::init();
|
||||
|
||||
let event_loop = EventLoop::builder().build().unwrap();
|
||||
//let event_loop = EventLoop::builder().with_x11().build().unwrap();
|
||||
|
||||
// When the current loop iteration finishes, immediately begin a new
|
||||
// iteration regardless of whether or not new events are available to
|
||||
// process. Preferred for applications that want to render as fast as
|
||||
// possible, like games.
|
||||
event_loop.set_control_flow(ControlFlow::Poll);
|
||||
|
||||
// When the current loop iteration finishes, suspend the thread until
|
||||
// another event arrives. Helps keeping CPU utilization low if nothing
|
||||
// is happening, which is preferred if the application might be idling in
|
||||
// the background.
|
||||
// event_loop.set_control_flow(ControlFlow::Wait);
|
||||
|
||||
let mut app = App::default();
|
||||
event_loop.run_app(&mut app).unwrap();
|
||||
}
|
||||
|
||||
#[derive(AsStd140)]
|
||||
pub struct ChunkImmediate
|
||||
{
|
||||
mvp: Mat4,
|
||||
eye_pos: Vec3,
|
||||
root_color: Vec4,
|
||||
root_subdiv: bool,
|
||||
frame_timestamp: u32,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user