Skip to content
Snippets Groups Projects
Unverified Commit fc455c91 authored by John Hunter's avatar John Hunter :minidisc:
Browse files

implement ui

parent c455bc09
No related branches found
No related tags found
No related merge requests found
use egui::{Color32, Frame, Id, ScrollArea, TextEdit, TextStyle};
use egui_winit_vulkano::Gui;
fn sized_text(ui: &mut egui::Ui, text: impl Into<String>, size: f32) {
ui.label(egui::RichText::new(text).size(size));
}
const CODE: &str = r#"
# Some markup
```
let mut gui = Gui::new(&event_loop, renderer.surface(), renderer.queue());
```
Vulkan(o) is hard, that I know...
"#;
#[derive(Debug)]
pub struct GState {
pub cursor_sensitivity: f32,
pub move_speed: f32,
}
impl Default for GState {
fn default() -> Self {
Self {
cursor_sensitivity: 1.0,
move_speed: 1.0,
}
}
}
pub fn gui_up(gui: &mut Gui, state: &mut GState) {
let mut code = CODE.to_owned();
gui.immediate_ui(|gui| {
let ctx = gui.context();
egui::SidePanel::left(Id::new("main_left"))
.frame(Frame::default().fill(Color32::from_rgba_unmultiplied(100, 100, 100, 200)))
.show(&ctx, |ui| {
ui.vertical_centered(|ui| {
ui.add(egui::widgets::Label::new("Efficient Realtime Rendering of Complex Closed Form Implicit Surfaces Using Modern RTX Enabled GPUs"));
sized_text(ui, "Settings", 32.0);
});
ui.separator();
ui.vertical_centered(|ui| {
//ui.heading("Camera Control");
ui.add(egui::Slider::new(&mut state.cursor_sensitivity, 0.0..=2.0).text("Mouse Sensitivity"));
ui.add(egui::Slider::new(&mut state.move_speed, 0.0..=2.0).text("Movement Speed"));
});
});
});
}
...@@ -16,23 +16,24 @@ ...@@ -16,23 +16,24 @@
// and that you want to learn Vulkan. This means that for example it won't go into details about // and that you want to learn Vulkan. This means that for example it won't go into details about
// what a vertex or a shader is. // what a vertex or a shader is.
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use cgmath::{Matrix3, Matrix4, Point3, Rad, Vector3}; use cgmath::{
AbsDiffEq, Basis3, Deg, EuclideanSpace, Euler, Matrix3, Matrix4, Point3, Quaternion, Rad,
SquareMatrix, Transform, Vector3,
};
use obj::{LoadConfig, ObjData}; use obj::{LoadConfig, ObjData};
use rodio::{source::Source, Decoder, OutputStream}; use rodio::{source::Source, Decoder, OutputStream};
use std::io::Cursor; use std::io::Cursor;
use std::{sync::Arc, time::Instant}; use std::{sync::Arc, time::Instant};
use vulkano::buffer::CpuBufferPool;
use vulkano::command_buffer::allocator::StandardCommandBufferAllocator; use vulkano::command_buffer::allocator::StandardCommandBufferAllocator;
use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator;
use vulkano::device::QueueFlags;
use vulkano::format::Format; use vulkano::format::Format;
use vulkano::image::AttachmentImage; use vulkano::image::AttachmentImage;
use vulkano::memory::allocator::{MemoryAllocator, MemoryUsage, StandardMemoryAllocator}; use vulkano::memory::allocator::StandardMemoryAllocator;
use vulkano::pipeline::graphics::depth_stencil::DepthStencilState; use vulkano::pipeline::graphics::depth_stencil::DepthStencilState;
use vulkano::pipeline::graphics::rasterization::CullMode; use vulkano::pipeline::graphics::rasterization::CullMode;
use vulkano::pipeline::graphics::rasterization::FrontFace::Clockwise; use vulkano::pipeline::graphics::rasterization::FrontFace::Clockwise;
use vulkano::swapchain::SwapchainPresentInfo; use vulkano::swapchain::{PresentMode, SwapchainPresentInfo};
use vulkano::{memory, VulkanLibrary}; use vulkano::VulkanLibrary;
use winit::event::{DeviceEvent, DeviceId, ElementState, MouseButton, VirtualKeyCode};
use egui_winit_vulkano::Gui; use egui_winit_vulkano::Gui;
use vulkano::pipeline::StateMode::Fixed; use vulkano::pipeline::StateMode::Fixed;
...@@ -41,7 +42,6 @@ use vulkano::{ ...@@ -41,7 +42,6 @@ use vulkano::{
command_buffer::{ command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents, AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
}, },
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
}, },
...@@ -55,7 +55,7 @@ use vulkano::{ ...@@ -55,7 +55,7 @@ use vulkano::{
vertex_input::BuffersDefinition, vertex_input::BuffersDefinition,
viewport::{Viewport, ViewportState}, viewport::{Viewport, ViewportState},
}, },
GraphicsPipeline, Pipeline, PipelineBindPoint, GraphicsPipeline, Pipeline,
}, },
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
swapchain::{ swapchain::{
...@@ -70,6 +70,9 @@ use winit::{ ...@@ -70,6 +70,9 @@ use winit::{
window::{Window, WindowBuilder}, window::{Window, WindowBuilder},
}; };
use crate::gui::*;
mod gui;
fn main() { fn main() {
// The first step of any Vulkan program is to create an instance. // The first step of any Vulkan program is to create an instance.
// //
...@@ -213,9 +216,6 @@ fn main() { ...@@ -213,9 +216,6 @@ fn main() {
// iterator. // iterator.
let queue = queues.next().expect("Unable to retrieve queues"); let queue = queues.next().expect("Unable to retrieve queues");
// Create an egui GUI
let mut gui = Gui::new(&event_loop, surface.clone(), None, queue.clone(), false);
// Before we can draw on the surface, we have to create what is called a swapchain. Creating // Before we can draw on the surface, we have to create what is called a swapchain. Creating
// a swapchain allocates the color buffers that will contain the image that will ultimately // a swapchain allocates the color buffers that will contain the image that will ultimately
// be visible on the screen. These images are returned alongside the swapchain. // be visible on the screen. These images are returned alongside the swapchain.
...@@ -276,6 +276,8 @@ fn main() { ...@@ -276,6 +276,8 @@ fn main() {
.next() .next()
.unwrap(), .unwrap(),
present_mode: PresentMode::FifoRelaxed,
..Default::default() ..Default::default()
}, },
) )
...@@ -393,7 +395,7 @@ fn main() { ...@@ -393,7 +395,7 @@ fn main() {
// The next step is to create a *render pass*, which is an object that describes where the // The next step is to create a *render pass*, which is an object that describes where the
// output of the graphics pipeline will go. It describes the layout of the images // output of the graphics pipeline will go. It describes the layout of the images
// where the colors, depth and/or stencil information will be written. // where the colors, depth and/or stencil information will be written.
let render_pass = vulkano::single_pass_renderpass!( let render_pass = vulkano::ordered_passes_renderpass!(
device.clone(), device.clone(),
attachments: { attachments: {
// `color` is a custom name we give to the first and only attachment. // `color` is a custom name we give to the first and only attachment.
...@@ -421,12 +423,19 @@ fn main() { ...@@ -421,12 +423,19 @@ fn main() {
samples: 1, samples: 1,
} }
}, },
pass: { passes: [{
// We use the attachment named `color` as the one and only color attachment. // We use the attachment named `color` as the one and only color attachment.
color: [color], color: [color],
// No depth-stencil attachment is indicated with empty brackets. // No depth-stencil attachment is indicated with empty brackets.
depth_stencil: {depth} depth_stencil: {depth},
} input: []
},{
// We use the attachment named `color` as the one and only color attachment.
color: [color],
// No depth-stencil attachment is indicated with empty brackets.
depth_stencil: {depth},
input: []
}]
) )
.unwrap(); .unwrap();
...@@ -504,6 +513,7 @@ fn main() { ...@@ -504,6 +513,7 @@ fn main() {
// that, we store the submission of the previous frame here. // that, we store the submission of the previous frame here.
let mut previous_frame_end = Some(sync::now(device.clone()).boxed()); let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
/*
// Get a output stream handle to the default physical sound device // Get a output stream handle to the default physical sound device
let (_stream, stream_handle) = OutputStream::try_default().unwrap(); let (_stream, stream_handle) = OutputStream::try_default().unwrap();
// Load a sound from a file, using a path relative to Cargo.toml // Load a sound from a file, using a path relative to Cargo.toml
...@@ -512,24 +522,101 @@ fn main() { ...@@ -512,24 +522,101 @@ fn main() {
let source = Decoder::new(freebird).unwrap().repeat_infinite(); let source = Decoder::new(freebird).unwrap().repeat_infinite();
// Play the sound directly on the device // Play the sound directly on the device
stream_handle.play_raw(source.convert_samples()).unwrap(); stream_handle.play_raw(source.convert_samples()).unwrap();
*/
let rotation_start = Instant::now(); let rotation_start = Instant::now();
//let descriptor_set_allocator = StandardDescriptorSetAllocator::new(device.clone()); //let descriptor_set_allocator = StandardDescriptorSetAllocator::new(device.clone());
// Create an egui GUI
let mut gui = Gui::new_with_subpass(
&event_loop,
surface.clone(),
None,
queue.clone(),
Subpass::from(render_pass.clone(), 1).unwrap(),
);
let mut gstate = GState::default();
let mut campos = Point3 {
x: 0f32,
y: 0f32,
z: 3f32,
};
let mut camforward = Euler::new(Deg(0f32), Deg(0f32), Deg(0f32));
let mut looking = false;
struct Keys {
w: bool,
s: bool,
a: bool,
d: bool,
}
let mut keys = Keys {
w: false,
s: false,
a: false,
d: false,
};
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, _, control_flow| {
match event { if let Event::WindowEvent { event: we, .. } = &event {
Event::WindowEvent { if !gui.update(we) {
event: WindowEvent::CloseRequested, match &we {
.. WindowEvent::CloseRequested => {
} => { *control_flow = ControlFlow::Exit;
*control_flow = ControlFlow::Exit; }
WindowEvent::Resized(_) => {
recreate_swapchain = true;
}
WindowEvent::ScaleFactorChanged { .. } => {
recreate_swapchain = true;
}
WindowEvent::DroppedFile(file) => {
todo!()
}
WindowEvent::MouseInput {
device_id: d,
state: s,
button: b,
..
} => {
println!("MOUSE {:?}, {:?}, {:?}", d, s, b);
if b == &MouseButton::Right {
looking = s == &ElementState::Pressed;
}
}
WindowEvent::KeyboardInput { input, .. } => match input.virtual_keycode {
Some(VirtualKeyCode::W) => {
keys.w = input.state == ElementState::Pressed;
}
Some(VirtualKeyCode::S) => {
keys.s = input.state == ElementState::Pressed;
}
Some(VirtualKeyCode::A) => {
keys.a = input.state == ElementState::Pressed;
}
Some(VirtualKeyCode::D) => {
keys.d = input.state == ElementState::Pressed;
}
_ => {}
},
_ => {}
}
} }
Event::WindowEvent { }
event: WindowEvent::Resized(_), match event {
Event::DeviceEvent {
event: DeviceEvent::MouseMotion { delta },
.. ..
} => { } => {
recreate_swapchain = true; if looking {
camforward.x -= Deg(delta.1 as f32) * gstate.cursor_sensitivity;
camforward.y += Deg(delta.0 as f32) * gstate.cursor_sensitivity;
}
//println!("AXISM {:?}", delta);
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
// Do not draw frame when screen dimensions are zero. // Do not draw frame when screen dimensions are zero.
...@@ -575,11 +662,44 @@ fn main() { ...@@ -575,11 +662,44 @@ fn main() {
recreate_swapchain = false; recreate_swapchain = false;
} }
//println!("{:?}", right);
let uniform_data = { let uniform_data = {
let elapsed = rotation_start.elapsed(); if looking {
let rotation = if keys.w {
elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1_000_000_000.0; campos -= Matrix3::from_angle_y(camforward.y)
let rotation = Matrix3::from_angle_y(Rad(rotation as f32)); * Matrix3::from_angle_x(camforward.x)
* Vector3::unit_z()
* 0.02
* gstate.move_speed;
}
if keys.s {
campos += Matrix3::from_angle_y(camforward.y)
* Matrix3::from_angle_x(camforward.x)
* Vector3::unit_z()
* 0.02
* gstate.move_speed;
}
if keys.a {
campos += Matrix3::from_angle_y(camforward.y)
* Matrix3::from_angle_x(camforward.x)
* Vector3::unit_x()
* 0.02
* gstate.move_speed;
}
if keys.d {
campos -= Matrix3::from_angle_y(camforward.y)
* Matrix3::from_angle_x(camforward.x)
* Vector3::unit_x()
* 0.02
* gstate.move_speed;
}
} else {
keys.w = false;
keys.s = false;
keys.a = false;
keys.d = false;
}
// note: this teapot was meant for OpenGL where the origin is at the lower left // note: this teapot was meant for OpenGL where the origin is at the lower left
// instead the origin is at the upper left in Vulkan, so we reverse the Y axis // instead the origin is at the upper left in Vulkan, so we reverse the Y axis
...@@ -591,25 +711,28 @@ fn main() { ...@@ -591,25 +711,28 @@ fn main() {
0.01, 0.01,
100.0, 100.0,
); );
let view = Matrix4::look_at_rh( let scale = 0.01;
Point3::new(0.3, 0.3, 1.0), let view = Matrix4::from(camforward)
Point3::new(0.0, 0.0, 0.0), * Matrix4::from_angle_z(Deg(180f32))
Vector3::new(0.0, -1.0, 0.0), * Matrix4::from_translation(Point3::origin() - campos)
); * Matrix4::from_scale(scale);
let scale = Matrix4::from_scale(0.01); //*Matrix4::from_angle_z(Deg(180f32));
vs::ty::PushConstantData { let pc = vs::ty::PushConstantData {
world: Matrix4::from(rotation).into(), world: Matrix4::identity().into(),
view: (view * scale).into(), view: view.into(),
proj: proj.into(), proj: proj.into(),
} };
/*println!( if looking {
"world: {:?} view: {:?} proj: {:?}", /*println!(
uniform_data.world, uniform_data.view, uniform_data.proj "world: {:?} view: {:?} proj: {:?}",
);*/ pc.world, pc.view, pc.proj
);*/
println!("campos: {:?} camforward: {:?}", campos, camforward);
}
//uniform_buffer.from_data(uniform_data).unwrap() pc
}; };
//let layout = pipeline.layout().set_layouts().get(0).unwrap(); //let layout = pipeline.layout().set_layouts().get(0).unwrap();
...@@ -644,6 +767,8 @@ fn main() { ...@@ -644,6 +767,8 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
gui_up(&mut gui, &mut gstate);
// In order to draw, we have to build a *command buffer*. The command buffer object holds // In order to draw, we have to build a *command buffer*. The command buffer object holds
// the list of commands that are going to be executed. // the list of commands that are going to be executed.
// //
...@@ -660,6 +785,8 @@ fn main() { ...@@ -660,6 +785,8 @@ fn main() {
) )
.unwrap(); .unwrap();
let cb = gui.draw_on_subpass_image(dimensions.into());
builder builder
// Before we can draw, we have to *enter a render pass*. // Before we can draw, we have to *enter a render pass*.
.begin_render_pass( .begin_render_pass(
...@@ -702,6 +829,10 @@ fn main() { ...@@ -702,6 +829,10 @@ fn main() {
.unwrap() .unwrap()
// We leave the render pass. Note that if we had multiple // We leave the render pass. Note that if we had multiple
// subpasses we could have called `next_subpass` to jump to the next subpass. // subpasses we could have called `next_subpass` to jump to the next subpass.
.next_subpass(SubpassContents::SecondaryCommandBuffers)
.unwrap()
.execute_commands(cb)
.unwrap()
.end_render_pass() .end_render_pass()
.unwrap(); .unwrap();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment