Compare commits

...

6 Commits

Author SHA1 Message Date
Jonas H
d888dc077e cargo imgui and sdl update 2026-03-04 09:08:19 +01:00
Jonas H
adeb181d17 ignored cargo.lock 2026-03-04 09:08:01 +01:00
Jonas H
0ce4e813ab draw/event cleanup and gitignore 2026-03-04 09:06:49 +01:00
Jonas H
322b1f7b43 editor+1 2026-03-04 09:05:39 +01:00
Jonas H
1925ebea0c sdl->28 2026-03-04 09:04:58 +01:00
Jonas H
5f8d924a02 editor with imgui and sdl->28 2026-03-04 09:04:37 +01:00
20 changed files with 362 additions and 2684 deletions

4
.gitignore vendored
View File

@@ -1,2 +1,6 @@
/target /target
target target
Cargo.lock
imgui.ini

2436
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,8 +4,12 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
sdl3 = { version = "0.16", features = ["raw-window-handle"] } sdl3 = { version = "0.17", features = ["raw-window-handle"] }
wgpu = "27" sdl3-sys = "0.6"
dear-imgui-rs = "0.10"
dear-imgui-wgpu = "0.10"
dear-imgui-sdl3 = "0.10"
wgpu = "28"
pollster = "0.3" pollster = "0.3"
glam = "0.30" glam = "0.30"
anyhow = "1.0" anyhow = "1.0"

View File

@@ -1,71 +0,0 @@
use std::collections::HashMap;
use std::rc::Rc;
use crate::entity::EntityHandle;
use crate::loaders::mesh::Mesh;
use crate::render::{DrawCall, Pipeline};
pub type DrawHandle = usize;
struct DrawEntry
{
mesh: Rc<Mesh>,
entity: EntityHandle,
pipeline: Pipeline,
}
pub struct DrawManager
{
entries: HashMap<DrawHandle, DrawEntry>,
next_handle: DrawHandle,
}
impl DrawManager
{
pub fn new() -> Self
{
Self {
entries: HashMap::new(),
next_handle: 0,
}
}
pub fn draw_mesh_internal(
&mut self,
mesh: Rc<Mesh>,
entity: EntityHandle,
pipeline: Pipeline,
) -> DrawHandle
{
let handle = self.next_handle;
self.next_handle += 1;
self.entries.insert(
handle,
DrawEntry {
mesh,
entity,
pipeline,
},
);
handle
}
pub fn clear_mesh_internal(&mut self, handle: DrawHandle)
{
self.entries.remove(&handle);
}
pub fn collect_draw_calls(&self) -> Vec<DrawCall>
{
vec![]
}
pub fn draw_mesh(_mesh: Rc<Mesh>, _entity: EntityHandle, _pipeline: Pipeline) -> DrawHandle
{
0
}
pub fn clear_mesh(_handle: DrawHandle) {}
}

98
src/editor/inspector.rs Normal file
View File

@@ -0,0 +1,98 @@
use dear_imgui_rs::{Condition, Context};
use dear_imgui_wgpu::{WgpuInitInfo, WgpuRenderer};
use sdl3_sys::events::SDL_Event;
pub struct FrameStats
{
pub fps: f32,
pub frame_ms: f32,
pub physics_budget_ms: f32,
pub draw_call_count: usize,
}
pub struct Inspector
{
imgui: Context,
renderer: WgpuRenderer,
}
impl Inspector
{
pub fn new(
device: &wgpu::Device,
queue: &wgpu::Queue,
surface_format: wgpu::TextureFormat,
) -> Self
{
let mut imgui = Context::create();
let init_info = WgpuInitInfo::new(device.clone(), queue.clone(), surface_format);
let renderer =
WgpuRenderer::new(init_info, &mut imgui).expect("Failed to create imgui wgpu renderer");
Self { imgui, renderer }
}
pub fn init_platform(&mut self, window: &sdl3::video::Window)
{
dear_imgui_sdl3::init_for_other(&mut self.imgui, window)
.expect("Failed to init imgui sdl3 platform");
}
pub fn begin_frame(&mut self)
{
dear_imgui_sdl3::sdl3_new_frame(&mut self.imgui);
}
pub fn process_event(&mut self, raw_event: &SDL_Event)
{
dear_imgui_sdl3::process_sys_event(raw_event);
}
pub fn wants_keyboard(&self) -> bool
{
self.imgui.io().want_capture_keyboard()
}
pub fn wants_mouse(&self) -> bool
{
self.imgui.io().want_capture_mouse()
}
pub fn build_ui(&mut self, stats: &FrameStats)
{
let ui = self.imgui.frame();
ui.window("Inspector")
.position([10.0, 10.0], Condition::FirstUseEver)
.build(|| {
ui.text(format!("FPS: {:.1}", stats.fps));
ui.text(format!("Frame: {:.1} ms", stats.frame_ms));
ui.text(format!("Physics: {:.1} ms", stats.physics_budget_ms));
ui.text(format!("Draw calls: {}", stats.draw_call_count));
});
}
pub fn render(&mut self, encoder: &mut wgpu::CommandEncoder, view: &wgpu::TextureView)
{
let draw_data = self.imgui.render();
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("ImGui Render Pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Load,
store: wgpu::StoreOp::Store,
},
depth_slice: None,
})],
depth_stencil_attachment: None,
occlusion_query_set: None,
timestamp_writes: None,
multiview_mask: None,
});
self.renderer
.render_draw_data(draw_data, &mut render_pass)
.expect("Failed to render imgui");
}
}

82
src/editor/mod.rs Normal file
View File

@@ -0,0 +1,82 @@
mod inspector;
use sdl3_sys::events::SDL_Event;
use crate::entity::EntityHandle;
use crate::systems::camera_noclip_system;
use crate::utility::input::InputState;
use crate::world::World;
pub use inspector::FrameStats;
use inspector::Inspector;
pub struct EditorState
{
pub active: bool,
pub right_mouse_held: bool,
pub selected_entity: Option<EntityHandle>,
inspector: Inspector,
}
impl EditorState
{
pub fn new(
device: &wgpu::Device,
queue: &wgpu::Queue,
surface_format: wgpu::TextureFormat,
) -> Self
{
Self {
active: false,
right_mouse_held: false,
selected_entity: None,
inspector: Inspector::new(device, queue, surface_format),
}
}
pub fn init_platform(&mut self, window: &sdl3::video::Window)
{
self.inspector.init_platform(window);
}
pub fn begin_frame(&mut self)
{
self.inspector.begin_frame();
}
pub fn process_event(&mut self, raw_event: &SDL_Event) -> bool
{
self.inspector.process_event(raw_event);
false
}
pub fn wants_keyboard(&self) -> bool
{
self.inspector.wants_keyboard()
}
pub fn wants_mouse(&self) -> bool
{
self.inspector.wants_mouse()
}
pub fn render(&mut self, encoder: &mut wgpu::CommandEncoder, view: &wgpu::TextureView)
{
self.inspector.render(encoder, view);
}
}
pub fn editor_loop(
editor: &mut EditorState,
world: &mut World,
input_state: &InputState,
stats: &FrameStats,
delta: f32,
)
{
if editor.right_mouse_held
{
camera_noclip_system(world, input_state, delta);
}
editor.inspector.build_ui(stats);
}

View File

@@ -1,70 +0,0 @@
use std::any::{Any, TypeId};
use std::cell::RefCell;
use std::collections::HashMap;
pub trait Event: std::fmt::Debug {}
type EventHandler<T> = Box<dyn FnMut(&T)>;
pub struct EventBus
{
handlers: HashMap<TypeId, Box<dyn Any>>,
}
impl EventBus
{
fn new() -> Self
{
Self {
handlers: HashMap::new(),
}
}
fn subscribe_internal<T: Event + 'static, F: FnMut(&T) + 'static>(&mut self, handler: F)
{
let type_id = TypeId::of::<T>();
let handlers: &mut Vec<EventHandler<T>> = self
.handlers
.entry(type_id)
.or_insert_with(|| Box::new(Vec::<EventHandler<T>>::new()))
.downcast_mut()
.unwrap();
handlers.push(Box::new(handler));
}
fn publish_internal<T: Event + 'static>(&mut self, event: &T)
{
let type_id = TypeId::of::<T>();
if let Some(handlers) = self.handlers.get_mut(&type_id)
{
let typed_handlers = handlers.downcast_mut::<Vec<EventHandler<T>>>().unwrap();
for handler in typed_handlers
{
handler(event);
}
}
}
pub fn subscribe<T: Event + 'static, F: FnMut(&T) + 'static>(handler: F)
{
EVENT_BUS.with(|bus| bus.borrow_mut().subscribe_internal(handler));
}
pub fn publish<T: Event + 'static>(event: &T)
{
EVENT_BUS.with(|bus| bus.borrow_mut().publish_internal(event));
}
}
thread_local! {
static EVENT_BUS: RefCell<EventBus> = RefCell::new(EventBus::new());
}
#[derive(Debug, Clone)]
pub struct UpdateEvent
{
pub delta: f32,
}
impl Event for UpdateEvent {}

View File

@@ -59,7 +59,7 @@ pub fn load_exr_heightmap(
address_mode_w: wgpu::AddressMode::ClampToEdge, address_mode_w: wgpu::AddressMode::ClampToEdge,
mag_filter: wgpu::FilterMode::Nearest, mag_filter: wgpu::FilterMode::Nearest,
min_filter: wgpu::FilterMode::Nearest, min_filter: wgpu::FilterMode::Nearest,
mipmap_filter: wgpu::FilterMode::Nearest, mipmap_filter: wgpu::MipmapFilterMode::Nearest,
..Default::default() ..Default::default()
}); });

View File

@@ -1,9 +1,8 @@
mod bundles; mod bundles;
mod components; mod components;
mod debug; mod debug;
mod draw; mod editor;
mod entity; mod entity;
mod event;
mod loaders; mod loaders;
mod physics; mod physics;
mod postprocess; mod postprocess;
@@ -17,11 +16,15 @@ mod utility;
mod world; mod world;
use crate::debug::{collider_debug, DebugMode}; use crate::debug::{collider_debug, DebugMode};
use crate::editor::{editor_loop, EditorState, FrameStats};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use glam::Vec3; use glam::Vec3;
use render::Renderer; use render::Renderer;
use sdl3::event::Event;
use sdl3::keyboard::Keycode;
use sdl3::mouse::MouseButton;
use utility::input::InputState; use utility::input::InputState;
use world::World; use world::World;
@@ -34,11 +37,11 @@ use crate::loaders::scene::Space;
use crate::physics::PhysicsManager; use crate::physics::PhysicsManager;
use crate::snow::{SnowConfig, SnowLayer}; use crate::snow::{SnowConfig, SnowLayer};
use crate::systems::{ use crate::systems::{
camera_follow_system, camera_input_system, camera_noclip_system, camera_view_matrix, camera_follow_system, camera_input_system, camera_view_matrix, physics_sync_system,
noclip_toggle_system, physics_sync_system, player_input_system, render_system, rotate_system, player_input_system, render_system, rotate_system, snow_system, spotlight_sync_system,
snow_system, spotlight_sync_system, start_camera_following, state_machine_physics_system, start_camera_following, state_machine_physics_system, state_machine_system,
state_machine_system,
}; };
use crate::systems::camera::stop_camera_following;
use crate::utility::time::Time; use crate::utility::time::Time;
fn main() -> Result<(), Box<dyn std::error::Error>> fn main() -> Result<(), Box<dyn std::error::Error>>
@@ -55,6 +58,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
let renderer = pollster::block_on(Renderer::new(&window, 2))?; let renderer = pollster::block_on(Renderer::new(&window, 2))?;
render::init(renderer); render::init(renderer);
let mut editor = render::with_device(|device| {
render::with_queue(|queue| {
render::with_surface_format(|format| EditorState::new(device, queue, format))
})
});
editor.init_platform(&window);
let space = Space::load_space("meshes/terrain.gltf")?; let space = Space::load_space("meshes/terrain.gltf")?;
let terrain_config = TerrainConfig::default(); let terrain_config = TerrainConfig::default();
@@ -95,7 +105,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
render::set_snow_depth(&snow_layer.depth_texture_view); render::set_snow_depth(&snow_layer.depth_texture_view);
let mut noclip_mode = true;
let mut debug_mode = DebugMode::default(); let mut debug_mode = DebugMode::default();
let camera_entity = CameraBundle { let camera_entity = CameraBundle {
@@ -103,12 +112,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
} }
.spawn(&mut world) .spawn(&mut world)
.unwrap(); .unwrap();
if !noclip_mode start_camera_following(&mut world, camera_entity);
{
start_camera_following(&mut world, camera_entity);
}
let mut event_pump = sdl_context.event_pump()?; let _event_pump = sdl_context.event_pump()?;
let mut input_state = InputState::new(); let mut input_state = InputState::new();
sdl_context.mouse().set_relative_mouse_mode(&window, true); sdl_context.mouse().set_relative_mouse_mode(&window, true);
@@ -121,6 +127,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
const FIXED_TIMESTEP: f32 = 1.0 / 60.0; const FIXED_TIMESTEP: f32 = 1.0 / 60.0;
let mut physics_accumulator = 0.0; let mut physics_accumulator = 0.0;
let mut stats = FrameStats {
fps: 0.0,
frame_ms: 0.0,
physics_budget_ms: 0.0,
draw_call_count: 0,
};
'running: loop 'running: loop
{ {
let frame_start = Instant::now(); let frame_start = Instant::now();
@@ -128,11 +141,77 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
let delta = (frame_start - last_frame).as_secs_f32(); let delta = (frame_start - last_frame).as_secs_f32();
last_frame = frame_start; last_frame = frame_start;
for event in event_pump.poll_iter() editor.begin_frame();
{
let mouse_capture_changed = input_state.handle_event(&event);
if mouse_capture_changed while let Some(raw_event) = dear_imgui_sdl3::sdl3_poll_event_ll()
{
editor.process_event(&raw_event);
let event = Event::from_ll(raw_event);
match &event
{
Event::Quit { .. } =>
{
input_state.quit_requested = true;
continue;
}
Event::KeyDown {
keycode: Some(Keycode::I),
repeat: false,
..
} =>
{
editor.active = !editor.active;
if editor.active
{
sdl_context.mouse().set_relative_mouse_mode(&window, false);
editor.right_mouse_held = false;
input_state.mouse_captured = false;
}
else
{
input_state.mouse_captured = true;
sdl_context.mouse().set_relative_mouse_mode(&window, true);
}
continue;
}
Event::MouseButtonDown {
mouse_btn: MouseButton::Right,
..
} if editor.active =>
{
editor.right_mouse_held = true;
input_state.mouse_captured = true;
stop_camera_following(&mut world, camera_entity);
sdl_context.mouse().set_relative_mouse_mode(&window, true);
continue;
}
Event::MouseButtonUp {
mouse_btn: MouseButton::Right,
..
} if editor.active =>
{
editor.right_mouse_held = false;
input_state.mouse_captured = false;
start_camera_following(&mut world, camera_entity);
sdl_context.mouse().set_relative_mouse_mode(&window, false);
continue;
}
_ =>
{}
}
if editor.active && (editor.wants_keyboard() || editor.wants_mouse())
{
continue;
}
let capture_changed = input_state.handle_event(&event);
if capture_changed && !editor.active
{ {
sdl_context sdl_context
.mouse() .mouse()
@@ -145,10 +224,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
break 'running; break 'running;
} }
input_state.process_post_events();
noclip_toggle_system(&mut world, &input_state, camera_entity, &mut noclip_mode);
if input_state.debug_cycle_just_pressed if input_state.debug_cycle_just_pressed
{ {
debug_mode = debug_mode.cycle(); debug_mode = debug_mode.cycle();
@@ -157,9 +232,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
camera_input_system(&mut world, &input_state); camera_input_system(&mut world, &input_state);
if noclip_mode if editor.active
{ {
camera_noclip_system(&mut world, &input_state, delta); editor_loop(&mut editor, &mut world, &input_state, &stats, delta);
} }
else else
{ {
@@ -167,6 +242,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
player_input_system(&mut world, &input_state); player_input_system(&mut world, &input_state);
} }
let physics_start = Instant::now();
physics_accumulator += delta; physics_accumulator += delta;
while physics_accumulator >= FIXED_TIMESTEP while physics_accumulator >= FIXED_TIMESTEP
@@ -180,6 +257,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
physics_accumulator -= FIXED_TIMESTEP; physics_accumulator -= FIXED_TIMESTEP;
} }
stats.physics_budget_ms = physics_start.elapsed().as_secs_f32() * 1000.0;
state_machine_system(&mut world, delta); state_machine_system(&mut world, delta);
rotate_system(&mut world, delta); rotate_system(&mut world, delta);
@@ -187,7 +266,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
let spotlights = spotlight_sync_system(&world); let spotlights = spotlight_sync_system(&world);
render::update_spotlights(spotlights); render::update_spotlights(spotlights);
snow_system(&world, &mut snow_layer, noclip_mode); snow_system(&world, &mut snow_layer, editor.active);
let mut draw_calls = render_system(&world); let mut draw_calls = render_system(&world);
draw_calls.extend(snow_layer.get_draw_calls()); draw_calls.extend(snow_layer.get_draw_calls());
@@ -207,7 +286,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
{ {
let projection = camera_component.projection_matrix(); let projection = camera_component.projection_matrix();
render::render( stats.draw_call_count = draw_calls.len();
stats.fps = 1.0 / delta;
stats.frame_ms = delta * 1000.0;
let frame = render::render(
&view, &view,
&projection, &projection,
camera_transform.position, camera_transform.position,
@@ -217,6 +300,21 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
delta, delta,
debug_mode, debug_mode,
); );
if editor.active
{
let screen_view =
frame.texture.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = render::with_device(|d| {
d.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("ImGui Encoder"),
})
});
editor.render(&mut encoder, &screen_view);
render::with_queue(|q| q.submit(std::iter::once(encoder.finish())));
}
frame.present();
} }
} }
} }

View File

@@ -85,7 +85,7 @@ impl LowResFramebuffer
address_mode_w: wgpu::AddressMode::ClampToEdge, address_mode_w: wgpu::AddressMode::ClampToEdge,
mag_filter: wgpu::FilterMode::Nearest, mag_filter: wgpu::FilterMode::Nearest,
min_filter: wgpu::FilterMode::Nearest, min_filter: wgpu::FilterMode::Nearest,
mipmap_filter: wgpu::FilterMode::Nearest, mipmap_filter: wgpu::MipmapFilterMode::Nearest,
..Default::default() ..Default::default()
}); });
@@ -157,7 +157,7 @@ pub fn create_blit_pipeline(
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Blit Pipeline Layout"), label: Some("Blit Pipeline Layout"),
bind_group_layouts: &[bind_group_layout], bind_group_layouts: &[bind_group_layout],
push_constant_ranges: &[], immediate_size: 0,
}); });
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
@@ -194,7 +194,7 @@ pub fn create_blit_pipeline(
mask: !0, mask: !0,
alpha_to_coverage_enabled: false, alpha_to_coverage_enabled: false,
}, },
multiview: None, multiview_mask: None,
cache: None, cache: None,
}) })
} }

View File

@@ -61,13 +61,13 @@ impl DebugOverlay
let shadow_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let shadow_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Shadow Debug Pipeline Layout"), label: Some("Shadow Debug Pipeline Layout"),
bind_group_layouts: &[&shadow_bind_group_layout], bind_group_layouts: &[&shadow_bind_group_layout],
push_constant_ranges: &[], immediate_size: 0,
}); });
let snow_light_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let snow_light_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Snow Light Debug Pipeline Layout"), label: Some("Snow Light Debug Pipeline Layout"),
bind_group_layouts: &[&snow_light_bind_group_layout], bind_group_layouts: &[&snow_light_bind_group_layout],
push_constant_ranges: &[], immediate_size: 0,
}); });
let color_target = wgpu::ColorTargetState { let color_target = wgpu::ColorTargetState {
@@ -98,7 +98,7 @@ impl DebugOverlay
}, },
depth_stencil: None, depth_stencil: None,
multisample: wgpu::MultisampleState::default(), multisample: wgpu::MultisampleState::default(),
multiview: None, multiview_mask: None,
cache: None, cache: None,
}); });
@@ -125,7 +125,7 @@ impl DebugOverlay
}, },
depth_stencil: None, depth_stencil: None,
multisample: wgpu::MultisampleState::default(), multisample: wgpu::MultisampleState::default(),
multiview: None, multiview_mask: None,
cache: None, cache: None,
}); });
@@ -171,6 +171,7 @@ impl DebugOverlay
depth_stencil_attachment: None, depth_stencil_attachment: None,
timestamp_writes: None, timestamp_writes: None,
occlusion_query_set: None, occlusion_query_set: None,
multiview_mask: None,
}); });
pass.set_pipeline(&self.pipeline_shadow); pass.set_pipeline(&self.pipeline_shadow);
@@ -221,6 +222,7 @@ impl DebugOverlay
depth_stencil_attachment: None, depth_stencil_attachment: None,
timestamp_writes: None, timestamp_writes: None,
occlusion_query_set: None, occlusion_query_set: None,
multiview_mask: None,
}); });
pass.set_pipeline(&self.pipeline_snow_light); pass.set_pipeline(&self.pipeline_snow_light);

View File

@@ -248,7 +248,7 @@ impl Renderer
address_mode_w: wgpu::AddressMode::ClampToEdge, address_mode_w: wgpu::AddressMode::ClampToEdge,
mag_filter: wgpu::FilterMode::Linear, mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Linear, min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest, mipmap_filter: wgpu::MipmapFilterMode::Nearest,
compare: Some(wgpu::CompareFunction::LessEqual), compare: Some(wgpu::CompareFunction::LessEqual),
..Default::default() ..Default::default()
}); });
@@ -546,7 +546,7 @@ impl Renderer
time: f32, time: f32,
delta_time: f32, delta_time: f32,
debug_mode: DebugMode, debug_mode: DebugMode,
) ) -> wgpu::SurfaceTexture
{ {
let light_view_projections = self.calculate_light_view_projections(); let light_view_projections = self.calculate_light_view_projections();
@@ -647,6 +647,7 @@ impl Renderer
}), }),
timestamp_writes: None, timestamp_writes: None,
occlusion_query_set: None, occlusion_query_set: None,
multiview_mask: None,
}); });
let pipeline = match draw_call.pipeline let pipeline = match draw_call.pipeline
@@ -737,6 +738,7 @@ impl Renderer
), ),
timestamp_writes: None, timestamp_writes: None,
occlusion_query_set: None, occlusion_query_set: None,
multiview_mask: None,
}); });
wire_pass.set_pipeline(wireframe_pipeline); wire_pass.set_pipeline(wireframe_pipeline);
@@ -850,6 +852,7 @@ impl Renderer
depth_stencil_attachment: None, depth_stencil_attachment: None,
timestamp_writes: None, timestamp_writes: None,
occlusion_query_set: None, occlusion_query_set: None,
multiview_mask: None,
}); });
blit_pass.set_pipeline(&self.blit_pipeline); blit_pass.set_pipeline(&self.blit_pipeline);
@@ -860,7 +863,7 @@ impl Renderer
} }
self.queue.submit(std::iter::once(blit_encoder.finish())); self.queue.submit(std::iter::once(blit_encoder.finish()));
frame.present(); frame
} }
pub fn render_scale(&self) -> (u32, u32) pub fn render_scale(&self) -> (u32, u32)
@@ -1025,7 +1028,7 @@ pub fn render(
time: f32, time: f32,
delta_time: f32, delta_time: f32,
debug_mode: DebugMode, debug_mode: DebugMode,
) ) -> wgpu::SurfaceTexture
{ {
GLOBAL_RENDERER.with(|r| { GLOBAL_RENDERER.with(|r| {
let mut renderer = r.borrow_mut(); let mut renderer = r.borrow_mut();
@@ -1039,8 +1042,19 @@ pub fn render(
time, time,
delta_time, delta_time,
debug_mode, debug_mode,
); )
}); })
}
pub fn with_surface_format<F, R>(f: F) -> R
where
F: FnOnce(wgpu::TextureFormat) -> R,
{
GLOBAL_RENDERER.with(|r| {
let renderer = r.borrow();
let renderer = renderer.as_ref().expect("Renderer not set");
f(renderer.config.format)
})
} }
pub fn set_shadow_bias(bias: f32) pub fn set_shadow_bias(bias: f32)

View File

@@ -20,7 +20,7 @@ pub fn create_shadow_pipeline(
let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Shadow Pipeline Layout"), label: Some("Shadow Pipeline Layout"),
bind_group_layouts: &[bind_group_layout], bind_group_layouts: &[bind_group_layout],
push_constant_ranges: &[], immediate_size: 0,
}); });
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
@@ -57,7 +57,7 @@ pub fn create_shadow_pipeline(
mask: !0, mask: !0,
alpha_to_coverage_enabled: false, alpha_to_coverage_enabled: false,
}, },
multiview: None, multiview_mask: None,
cache: None, cache: None,
}) })
} }
@@ -85,7 +85,7 @@ pub fn create_main_pipeline(
let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Main Pipeline Layout"), label: Some("Main Pipeline Layout"),
bind_group_layouts: &[bind_group_layout], bind_group_layouts: &[bind_group_layout],
push_constant_ranges: &[], immediate_size: 0,
}); });
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
@@ -131,7 +131,7 @@ pub fn create_main_pipeline(
mask: !0, mask: !0,
alpha_to_coverage_enabled: false, alpha_to_coverage_enabled: false,
}, },
multiview: None, multiview_mask: None,
cache: None, cache: None,
}) })
} }
@@ -157,7 +157,7 @@ pub fn create_wireframe_pipeline(
let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Wireframe Pipeline Layout"), label: Some("Wireframe Pipeline Layout"),
bind_group_layouts: &[bind_group_layout], bind_group_layouts: &[bind_group_layout],
push_constant_ranges: &[], immediate_size: 0,
}); });
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
@@ -203,7 +203,7 @@ pub fn create_wireframe_pipeline(
mask: !0, mask: !0,
alpha_to_coverage_enabled: false, alpha_to_coverage_enabled: false,
}, },
multiview: None, multiview_mask: None,
cache: None, cache: None,
}) })
} }
@@ -229,7 +229,7 @@ pub fn create_debug_lines_pipeline(
let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Debug Lines Pipeline Layout"), label: Some("Debug Lines Pipeline Layout"),
bind_group_layouts: &[bind_group_layout], bind_group_layouts: &[bind_group_layout],
push_constant_ranges: &[], immediate_size: 0,
}); });
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
@@ -275,7 +275,7 @@ pub fn create_debug_lines_pipeline(
mask: !0, mask: !0,
alpha_to_coverage_enabled: false, alpha_to_coverage_enabled: false,
}, },
multiview: None, multiview_mask: None,
cache: None, cache: None,
}) })
} }
@@ -340,7 +340,7 @@ pub fn create_snow_clipmap_pipeline(
let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Snow Clipmap Pipeline Layout"), label: Some("Snow Clipmap Pipeline Layout"),
bind_group_layouts: &[main_bind_group_layout, &displacement_bind_group_layout], bind_group_layouts: &[main_bind_group_layout, &displacement_bind_group_layout],
push_constant_ranges: &[], immediate_size: 0,
}); });
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
@@ -390,7 +390,7 @@ pub fn create_snow_clipmap_pipeline(
mask: !0, mask: !0,
alpha_to_coverage_enabled: false, alpha_to_coverage_enabled: false,
}, },
multiview: None, multiview_mask: None,
cache: None, cache: None,
}) })
} }

View File

@@ -68,6 +68,7 @@ impl Renderer
}), }),
timestamp_writes: None, timestamp_writes: None,
occlusion_query_set: None, occlusion_query_set: None,
multiview_mask: None,
}); });
shadow_pass.set_pipeline( shadow_pass.set_pipeline(

View File

@@ -360,7 +360,7 @@ impl SnowLayer
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Snow Deform Pipeline Layout"), label: Some("Snow Deform Pipeline Layout"),
bind_group_layouts: &[&bind_group_layout], bind_group_layouts: &[&bind_group_layout],
push_constant_ranges: &[], immediate_size: 0,
}); });
let pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { let pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {

View File

@@ -1,5 +1,5 @@
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use glam::{Vec2, Vec3}; use glam::Vec2;
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
#[repr(C)] #[repr(C)]
@@ -185,7 +185,7 @@ impl SnowLightAccumulation
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Snow Light Accumulation Pipeline Layout"), label: Some("Snow Light Accumulation Pipeline Layout"),
bind_group_layouts: &[&bind_group_layout], bind_group_layouts: &[&bind_group_layout],
push_constant_ranges: &[], immediate_size: 0,
}); });
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
@@ -222,7 +222,7 @@ impl SnowLightAccumulation
mask: !0, mask: !0,
alpha_to_coverage_enabled: false, alpha_to_coverage_enabled: false,
}, },
multiview: None, multiview_mask: None,
cache: None, cache: None,
}); });
@@ -280,6 +280,7 @@ impl SnowLightAccumulation
depth_stencil_attachment: None, depth_stencil_attachment: None,
timestamp_writes: None, timestamp_writes: None,
occlusion_query_set: None, occlusion_query_set: None,
multiview_mask: None,
}); });
encoder.begin_render_pass(&wgpu::RenderPassDescriptor { encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
@@ -296,6 +297,7 @@ impl SnowLightAccumulation
depth_stencil_attachment: None, depth_stencil_attachment: None,
timestamp_writes: None, timestamp_writes: None,
occlusion_query_set: None, occlusion_query_set: None,
multiview_mask: None,
}); });
} }
@@ -498,6 +500,7 @@ impl SnowLightAccumulation
depth_stencil_attachment: None, depth_stencil_attachment: None,
timestamp_writes: None, timestamp_writes: None,
occlusion_query_set: None, occlusion_query_set: None,
multiview_mask: None,
}); });
render_pass.set_pipeline(&self.pipeline); render_pass.set_pipeline(&self.pipeline);

View File

@@ -1,7 +1,6 @@
pub mod camera; pub mod camera;
pub mod follow; pub mod follow;
pub mod input; pub mod input;
pub mod noclip;
pub mod physics_sync; pub mod physics_sync;
pub mod player_states; pub mod player_states;
pub mod render; pub mod render;
@@ -16,7 +15,6 @@ pub use camera::{
start_camera_following, start_camera_following,
}; };
pub use input::player_input_system; pub use input::player_input_system;
pub use noclip::noclip_toggle_system;
pub use physics_sync::physics_sync_system; pub use physics_sync::physics_sync_system;
pub use render::render_system; pub use render::render_system;
pub use rotate::rotate_system; pub use rotate::rotate_system;

View File

@@ -1,25 +0,0 @@
use crate::entity::EntityHandle;
use crate::systems::camera::{start_camera_following, stop_camera_following};
use crate::utility::input::InputState;
use crate::world::World;
pub fn noclip_toggle_system(
world: &mut World,
input_state: &InputState,
camera_entity: EntityHandle,
noclip_mode: &mut bool,
)
{
if input_state.noclip_just_pressed
{
*noclip_mode = !*noclip_mode;
if *noclip_mode
{
stop_camera_following(world, camera_entity);
}
else
{
start_camera_following(world, camera_entity);
}
}
}

View File

@@ -123,7 +123,7 @@ impl DitherTextures
address_mode_w: wgpu::AddressMode::Repeat, address_mode_w: wgpu::AddressMode::Repeat,
mag_filter: wgpu::FilterMode::Nearest, mag_filter: wgpu::FilterMode::Nearest,
min_filter: wgpu::FilterMode::Nearest, min_filter: wgpu::FilterMode::Nearest,
mipmap_filter: wgpu::FilterMode::Nearest, mipmap_filter: wgpu::MipmapFilterMode::Nearest,
..Default::default() ..Default::default()
}); });
@@ -226,7 +226,7 @@ impl FlowmapTexture
address_mode_w: wgpu::AddressMode::Repeat, address_mode_w: wgpu::AddressMode::Repeat,
mag_filter: wgpu::FilterMode::Nearest, mag_filter: wgpu::FilterMode::Nearest,
min_filter: wgpu::FilterMode::Nearest, min_filter: wgpu::FilterMode::Nearest,
mipmap_filter: wgpu::FilterMode::Nearest, mipmap_filter: wgpu::MipmapFilterMode::Nearest,
..Default::default() ..Default::default()
}); });

View File

@@ -11,12 +11,10 @@ pub struct InputState
pub shift: bool, pub shift: bool,
pub space_just_pressed: bool, pub space_just_pressed: bool,
pub noclip_just_pressed: bool,
pub debug_cycle_just_pressed: bool, pub debug_cycle_just_pressed: bool,
pub mouse_delta: (f32, f32), pub mouse_delta: (f32, f32),
pub mouse_captured: bool, pub mouse_captured: bool,
pub noclip_mode: bool,
pub quit_requested: bool, pub quit_requested: bool,
} }
@@ -32,11 +30,9 @@ impl InputState
space: false, space: false,
shift: false, shift: false,
space_just_pressed: false, space_just_pressed: false,
noclip_just_pressed: false,
debug_cycle_just_pressed: false, debug_cycle_just_pressed: false,
mouse_delta: (0.0, 0.0), mouse_delta: (0.0, 0.0),
mouse_captured: true, mouse_captured: true,
noclip_mode: false,
quit_requested: false, quit_requested: false,
} }
} }
@@ -66,12 +62,6 @@ impl InputState
self.quit_requested = true; self.quit_requested = true;
return true; return true;
} }
if *key == Keycode::I
{
self.mouse_captured = !self.mouse_captured;
return true;
}
} }
} }
@@ -111,7 +101,6 @@ impl InputState
self.space = true; self.space = true;
} }
Keycode::LShift | Keycode::RShift => self.shift = true, Keycode::LShift | Keycode::RShift => self.shift = true,
Keycode::N => self.noclip_just_pressed = true,
Keycode::F1 => self.debug_cycle_just_pressed = true, Keycode::F1 => self.debug_cycle_just_pressed = true,
_ => _ =>
{} {}
@@ -141,22 +130,9 @@ impl InputState
} }
} }
pub fn process_post_events(&mut self)
{
if self.noclip_just_pressed
{
self.noclip_mode = !self.noclip_mode;
println!(
"Noclip mode: {}",
if self.noclip_mode { "ON" } else { "OFF" }
);
}
}
pub fn clear_just_pressed(&mut self) pub fn clear_just_pressed(&mut self)
{ {
self.space_just_pressed = false; self.space_just_pressed = false;
self.noclip_just_pressed = false;
self.debug_cycle_just_pressed = false; self.debug_cycle_just_pressed = false;
self.mouse_delta = (0.0, 0.0); self.mouse_delta = (0.0, 0.0);
} }