1
0
Fork 0

Add imgui

This commit is contained in:
Adrian Hedqvist 2020-11-26 17:17:41 +01:00
parent ab9d965630
commit 7a8b9a973c
4 changed files with 230 additions and 75 deletions

82
Cargo.lock generated
View file

@ -384,9 +384,9 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-epoch" name = "crossbeam-epoch"
version = "0.9.0" version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f" checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"const_fn", "const_fn",
@ -398,13 +398,12 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
dependencies = [ dependencies = [
"autocfg 1.0.1", "autocfg 1.0.1",
"cfg-if 1.0.0", "cfg-if 1.0.0",
"const_fn",
"lazy_static", "lazy_static",
] ]
@ -870,6 +869,50 @@ dependencies = [
"tiff", "tiff",
] ]
[[package]]
name = "imgui"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a714f73a3f08446d92c47a38b536a03deba500aa6bb6fa805e8c0b6f90945e4f"
dependencies = [
"bitflags",
"imgui-sys",
"lazy_static",
"parking_lot",
]
[[package]]
name = "imgui-sys"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0522b693da8a64322afbb32c63c04f39d9b9435cc75199d630207eee48886fc1"
dependencies = [
"cc",
]
[[package]]
name = "imgui-wgpu"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8017f74f8880049c1c3fc055868486a610178ab93ad18eadaf5b0bb52f738365"
dependencies = [
"bytemuck",
"imgui",
"log",
"smallvec",
"wgpu",
]
[[package]]
name = "imgui-winit-support"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e0fc247afc385ed9cd26860cdb7fae988d5c7e2ad1d70c70aef728ce9b78e85"
dependencies = [
"imgui",
"winit",
]
[[package]] [[package]]
name = "inplace_it" name = "inplace_it"
version = "0.3.2" version = "0.3.2"
@ -1017,9 +1060,9 @@ dependencies = [
[[package]] [[package]]
name = "memoffset" name = "memoffset"
version = "0.5.6" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
dependencies = [ dependencies = [
"autocfg 1.0.1", "autocfg 1.0.1",
] ]
@ -1184,9 +1227,9 @@ dependencies = [
[[package]] [[package]]
name = "nom" name = "nom"
version = "6.0.0" version = "6.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4489ccc7d668957ddf64af7cd027c081728903afa6479d35da7e99bf5728f75f" checksum = "88034cfd6b4a0d54dd14f4a507eceee36c0b70e5a02236c4e4df571102be17f0"
dependencies = [ dependencies = [
"memchr", "memchr",
"version_check", "version_check",
@ -1353,9 +1396,9 @@ dependencies = [
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.1.11" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c"
[[package]] [[package]]
name = "pin-utils" name = "pin-utils"
@ -1732,9 +1775,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.50" version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "443b4178719c5a851e1bde36ce12da21d74a0e60b4d982ec3385a933c812f0f6" checksum = "3b4f34193997d92804d359ed09953e25d5138df6bcc055a71bf68ee89fdf9223"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1813,11 +1856,11 @@ dependencies = [
[[package]] [[package]]
name = "tracing" name = "tracing"
version = "0.1.21" version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27" checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3"
dependencies = [ dependencies = [
"cfg-if 0.1.10", "cfg-if 1.0.0",
"pin-project-lite", "pin-project-lite",
"tracing-core", "tracing-core",
] ]
@ -2023,9 +2066,9 @@ checksum = "3e2bb9fc8309084dd7cd651336673844c1d47f8ef6d2091ec160b27f5c4aa277"
[[package]] [[package]]
name = "wgpu" name = "wgpu"
version = "0.6.0" version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "549160f188eef412ac978499ddf0ceadad4c9159bb1160f9e6b9d4cc8ee977dc" checksum = "991903e4c9f5b7319732b30a3d0339e27a51ea992cea22769b5f6c7f7076af6d"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"futures", "futures",
@ -2083,6 +2126,9 @@ dependencies = [
"futures", "futures",
"glob", "glob",
"image", "image",
"imgui",
"imgui-wgpu",
"imgui-winit-support",
"log", "log",
"shaderc", "shaderc",
"tobj", "tobj",

View file

@ -17,6 +17,9 @@ env_logger = "0.8"
log = "0.4" log = "0.4"
tobj = "2" tobj = "2"
cgmath = "0.17" cgmath = "0.17"
imgui = "0.6.0"
imgui-wgpu = "0.12.0"
imgui-winit-support = "0.6.0"
[build-dependencies] [build-dependencies]
shaderc = "0.7" shaderc = "0.7"

View file

@ -98,8 +98,7 @@ impl CameraController {
let f_spd = (self.speed * dt).min(forward_mag - 8.0); let f_spd = (self.speed * dt).min(forward_mag - 8.0);
if self.is_forward_pressed && forward_mag > f_spd { if self.is_forward_pressed && forward_mag > f_spd {
camera.eye += forward_norm * f_spd; camera.eye += forward_norm * f_spd;
} } else if self.is_backward_pressed {
else if self.is_backward_pressed {
camera.eye -= forward_norm * self.speed * dt; camera.eye -= forward_norm * self.speed * dt;
} }
forward = camera.target - camera.eye; forward = camera.target - camera.eye;
@ -111,10 +110,11 @@ impl CameraController {
if self.is_right_pressed != self.is_left_pressed { if self.is_right_pressed != self.is_left_pressed {
if self.is_right_pressed { if self.is_right_pressed {
camera.eye = camera.target - (forward - right * self.speed * dt).normalize() * forward_mag; camera.eye =
} camera.target - (forward - right * self.speed * dt).normalize() * forward_mag;
else if self.is_left_pressed { } else if self.is_left_pressed {
camera.eye = camera.target - (forward + right * self.speed * dt).normalize() * forward_mag; camera.eye =
camera.target - (forward + right * self.speed * dt).normalize() * forward_mag;
} }
} }
} }

View file

@ -1,3 +1,4 @@
use imgui::im_str;
use model::{DrawLight, DrawModel, Model, Vertex}; use model::{DrawLight, DrawModel, Model, Vertex};
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
use winit::{ use winit::{
@ -32,57 +33,62 @@ fn main() {
.build(&event_loop) .build(&event_loop)
.expect("Failed to create window"); .expect("Failed to create window");
let mut state = futures::executor::block_on(State::new(&window)); let mut state = futures::executor::block_on(State::new(window));
let mut previous_frame = std::time::Instant::now(); let mut last_frame = std::time::Instant::now();
let mut dt = std::time::Duration::new(0, 0);
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, _, control_flow| {
Event::WindowEvent { state
ref event, .imgui_platform
window_id, .handle_event(state.imgui.io_mut(), &state.window, &event);
} if window_id == window.id() => { match event {
if !state.input(event) { Event::WindowEvent {
match event { ref event,
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, window_id,
WindowEvent::KeyboardInput { input, .. } => { } if window_id == state.window.id() => {
if let KeyboardInput { if !state.input(event) {
state: ElementState::Pressed, match event {
virtual_keycode: Some(VirtualKeyCode::Escape), WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
.. WindowEvent::KeyboardInput { input, .. } => {
} = input if let KeyboardInput {
{ state: ElementState::Pressed,
*control_flow = ControlFlow::Exit virtual_keycode: Some(VirtualKeyCode::Escape),
..
} = input
{
*control_flow = ControlFlow::Exit
}
} }
WindowEvent::Resized(physical_size) => {
state.resize(*physical_size);
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
state.resize(**new_inner_size);
}
_ => {}
} }
WindowEvent::Resized(physical_size) => {
state.resize(*physical_size);
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
state.resize(**new_inner_size);
}
_ => {}
} }
} }
Event::RedrawRequested(_) => {
match state.render() {
Ok(_) => {}
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
Err(wgpu::SwapChainError::OutOfMemory) => {
eprintln!("Recieved a swapchain OOM error, exiting...");
*control_flow = ControlFlow::Exit;
}
Err(_) => {}
};
}
Event::MainEventsCleared => {
let now = std::time::Instant::now();
let dt = now - last_frame;
state.imgui.io_mut().update_delta_time(dt);
state.update(dt.as_secs_f32());
last_frame = now;
state.window.request_redraw();
}
_ => {}
} }
Event::RedrawRequested(_) => {
match state.render() {
Ok(_) => {}
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
Err(wgpu::SwapChainError::OutOfMemory) => {
eprintln!("Recieved a swapchain OOM error, exiting...");
*control_flow = ControlFlow::Exit;
}
Err(_) => {}
};
}
Event::MainEventsCleared => {
state.update(dt.as_secs_f32());
let now = std::time::Instant::now();
dt = now - previous_frame;
previous_frame = now;
window.request_redraw();
}
_ => {}
}); });
} }
@ -168,6 +174,7 @@ struct InstanceRaw {
} }
struct State { struct State {
window: Window,
_instance: wgpu::Instance, _instance: wgpu::Instance,
surface: wgpu::Surface, surface: wgpu::Surface,
_adapter: wgpu::Adapter, _adapter: wgpu::Adapter,
@ -197,14 +204,20 @@ struct State {
render_pipeline: wgpu::RenderPipeline, render_pipeline: wgpu::RenderPipeline,
size: winit::dpi::PhysicalSize<u32>, size: winit::dpi::PhysicalSize<u32>,
imgui: imgui::Context,
imgui_platform: imgui_winit_support::WinitPlatform,
imgui_renderer: imgui_wgpu::Renderer,
rotation_speed: f32,
} }
impl State { impl State {
async fn new(window: &Window) -> Self { async fn new(window: Window) -> Self {
let size = window.inner_size(); let size = window.inner_size();
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY); let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let surface = unsafe { instance.create_surface(window) }; let surface = unsafe { instance.create_surface(&window) };
let adapter = instance let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions { .request_adapter(&wgpu::RequestAdapterOptions {
@ -292,7 +305,7 @@ impl State {
(0..NUM_INSTANCES_PER_ROW).map(move |x| { (0..NUM_INSTANCES_PER_ROW).map(move |x| {
let x = SPACE_BETWEEN * (x as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0); let x = SPACE_BETWEEN * (x as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
let z = SPACE_BETWEEN * (z as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0); let z = SPACE_BETWEEN * (z as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
let position = Vec3 {x, y: 0.0, z}; let position = Vec3 { x, y: 0.0, z };
let rotation = if position.is_zero() { let rotation = if position.is_zero() {
cgmath::Quaternion::from_axis_angle(Vec3::unit_z(), cgmath::Deg(0.0)) cgmath::Quaternion::from_axis_angle(Vec3::unit_z(), cgmath::Deg(0.0))
@ -430,7 +443,43 @@ impl State {
let depth_texture = let depth_texture =
texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture"); texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
let mut imgui = imgui::Context::create();
let mut imgui_platform = imgui_winit_support::WinitPlatform::init(&mut imgui);
imgui_platform.attach_window(
imgui.io_mut(),
&window,
imgui_winit_support::HiDpiMode::Default,
);
imgui.set_ini_filename(None);
let hidpi_factor = window.scale_factor();
let font_size = (13.0 * hidpi_factor) as f32;
imgui.io_mut().font_global_scale = (1.0 / hidpi_factor) as f32;
imgui
.fonts()
.add_font(&[imgui::FontSource::DefaultFontData {
config: Some(imgui::FontConfig {
oversample_h: 1,
pixel_snap_h: true,
size_pixels: font_size,
..Default::default()
}),
}]);
let imgui_renderer = imgui_wgpu::Renderer::new(
&mut imgui,
&device,
&queue,
imgui_wgpu::RendererConfig {
texture_format: sc_desc.format,
..Default::default()
},
);
Self { Self {
window,
_instance: instance, _instance: instance,
surface, surface,
_adapter: adapter, _adapter: adapter,
@ -453,6 +502,10 @@ impl State {
instance_buffer, instance_buffer,
render_pipeline, render_pipeline,
size, size,
imgui,
imgui_platform,
imgui_renderer,
rotation_speed: 1.0,
} }
} }
@ -467,6 +520,16 @@ impl State {
} }
fn input(&mut self, event: &WindowEvent) -> bool { fn input(&mut self, event: &WindowEvent) -> bool {
if let WindowEvent::KeyboardInput { .. } = event {
if self.imgui.io().want_capture_keyboard {
return true;
}
} else if let WindowEvent::MouseInput { .. } = event {
if self.imgui.io().want_capture_mouse {
return true;
}
}
self.camera_controller.process_events(event) self.camera_controller.process_events(event)
} }
@ -504,14 +567,18 @@ impl State {
self.queue self.queue
.write_buffer(&self.light_buffer, 0, bytemuck::cast_slice(&[self.light])); .write_buffer(&self.light_buffer, 0, bytemuck::cast_slice(&[self.light]));
let deg = cgmath::Deg(30.0 * dt * self.rotation_speed);
for instance in &mut self.instances { for instance in &mut self.instances {
let deg = cgmath::Deg(30.0 * dt); let rot = cgmath::Quaternion::from(cgmath::Euler::new(deg, deg*1.1, deg*1.2));
let rot = cgmath::Quaternion::from(cgmath::Euler::new(deg, deg, deg));
instance.rotation = instance.rotation * rot; instance.rotation = instance.rotation * rot;
} }
let instance_data: Vec<_> = self.instances.iter().map(Instance::to_raw).collect(); let instance_data: Vec<_> = self.instances.iter().map(Instance::to_raw).collect();
self.queue.write_buffer(&self.instance_buffer, 0, bytemuck::cast_slice(&instance_data)); self.queue.write_buffer(
&self.instance_buffer,
0,
bytemuck::cast_slice(&instance_data),
);
self.queue.submit(Some(encoder.finish())); self.queue.submit(Some(encoder.finish()));
} }
@ -519,6 +586,24 @@ impl State {
fn render(&mut self) -> Result<(), wgpu::SwapChainError> { fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?; let frame = self.swap_chain.get_current_frame()?;
self.imgui_platform
.prepare_frame(self.imgui.io_mut(), &self.window)
.expect("Failed to prepare imgui frame");
let ui = self.imgui.frame();
{
let mut spd = self.rotation_speed;
imgui::Window::new(im_str!("wgpu tutorial!"))
.size([300.0, 100.0], imgui::Condition::FirstUseEver)
.build(&ui, || {
ui.text(im_str!("wooo!"));
imgui::Slider::new(im_str!("RotSpeed"))
.range(-10.0..=10.0)
.build(&ui, &mut spd);
});
self.rotation_speed = spd;
}
let mut encoder = self let mut encoder = self
.device .device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { .create_command_encoder(&wgpu::CommandEncoderDescriptor {
@ -568,6 +653,27 @@ impl State {
drop(render_pass); drop(render_pass);
self.imgui_platform.prepare_render(&ui, &self.window);
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.output.view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Load, // Do not clear
// load: wgpu::LoadOp::Clear(clear_color),
store: true,
},
}],
depth_stencil_attachment: None,
});
self.imgui_renderer
.render(ui.render(), &self.queue, &self.device, &mut rpass)
.expect("Failed to render UI!");
drop(rpass);
self.queue.submit(Some(encoder.finish())); self.queue.submit(Some(encoder.finish()));
Ok(()) Ok(())