,
}
@@ -28,8 +28,8 @@ impl GliumAssetManager {
impl ModelManager for GliumAssetManager {
fn load_gltf(&mut self, id: ModelID, path: &Path) {
- let models = load_gltf(path, self.facade.as_ref()).unwrap();
- self.models.insert(id, models);
+ let model = load_gltf(path, self.facade.as_ref()).unwrap();
+ self.models.insert(id, model);
}
fn unload_model(&mut self, id: ModelID) {
@@ -48,6 +48,6 @@ impl ModelManager for GliumAssetManager {
// }
fn get_model(&self, id: &ModelID) -> Option<&dyn Any> {
- self.models.get(id).map(|models| models as &dyn Any)
+ self.models.get(id).map(|model| model as &dyn Any)
}
}
diff --git a/glium_platform/src/gltf_loader.rs b/glium_platform/src/gltf_loader.rs
index fe4ec37..e41bbfb 100644
--- a/glium_platform/src/gltf_loader.rs
+++ b/glium_platform/src/gltf_loader.rs
@@ -1,4 +1,4 @@
-use anyhow::{bail, Context, Result};
+use anyhow::{Context, Result};
use glium::{backend::Facade, IndexBuffer, VertexBuffer};
use glium::index::PrimitiveType;
use std::{fmt::Debug, path::Path};
@@ -8,16 +8,31 @@ use glium::uniforms::{SamplerWrapFunction, MinifySamplerFilter, MagnifySamplerFi
use gltf::image::Format as GltfFormat;
use glam::Vec2;
-/// Load a glTF 2.0 file from disk and upload all primitives to the GPU.
-///
-/// Returns one [`Model`] per glTF primitive (across all meshes).
-pub fn load_gltf(path: P, facade: &dyn Facade) -> Result>
+/// Load a glTF 2.0 file from disk and upload the first primitive to the GPU.
+pub fn load_gltf(path: P, facade: &dyn Facade) -> Result
where
P: AsRef + Debug,
{
// -- parse the asset & bring buffer blobs into memory --
let (doc, buffers, images) = gltf::import(path.as_ref()).context("failed to import glTF file")?;
+ // -- grab the very first mesh / primitive --
+ let mesh = doc.meshes().next().context("glTF has no meshes")?;
+ let primitive = mesh.primitives().next().context("mesh has no primitives")?;
+
+ // ---------- MATERIAL ----------
+ let mut mat = Material::default();
+
+ let mat_idx = primitive.material().index().context("primitive has no material")?;
+ let material = doc.materials().nth(mat_idx).unwrap();
+ let pbr = material.pbr_metallic_roughness();
+
+ // Factors --------------------------------------------------
+ mat.base_color_factor = pbr.base_color_factor();
+ mat.metal_factor = pbr.metallic_factor();
+ mat.roughness_factor = pbr.roughness_factor();
+ mat.emissive_factor = material.emissive_factor();
+
// Helper to update sampler settings from glTF sampler
fn update_sampler(mat: &mut Material, t: &gltf::texture::Texture<'_>) {
let sampler_info = t.sampler();
@@ -49,92 +64,64 @@ where
}
}
- let mut out: Vec = Vec::new();
+ // Base-color texture (sRGB)
+ if let Some(info) = pbr.base_color_texture() {
+ update_sampler(&mut mat, &info.texture());
+ let view = info.texture().source().index();
+ mat.base_color = Some(glium_srgb_texture(facade, &images[view])?);
+ }
- for mesh in doc.meshes() {
- for primitive in mesh.primitives() {
- // ---------- MATERIAL ----------
- let mut mat = Material::default();
- let material = primitive.material();
- let pbr = material.pbr_metallic_roughness();
+ // Metallic-Roughness (linear)
+ if let Some(info) = pbr.metallic_roughness_texture() {
+ update_sampler(&mut mat, &info.texture());
+ let view = info.texture().source().index();
+ mat.metallic_roughness = Some(glium_linear_texture(facade, &images[view])?);
+ }
- // Factors --------------------------------------------------
- mat.base_color_factor = pbr.base_color_factor();
- mat.metal_factor = pbr.metallic_factor();
- mat.roughness_factor = pbr.roughness_factor();
- mat.emissive_factor = material.emissive_factor();
+ // Normal map (linear)
+ if let Some(info) = primitive.material().normal_texture() {
+ update_sampler(&mut mat, &info.texture());
+ let view = info.texture().source().index();
+ mat.normal = Some(glium_linear_texture(facade, &images[view])?);
+ }
- // Base-color texture (sRGB)
- if let Some(info) = pbr.base_color_texture() {
- update_sampler(&mut mat, &info.texture());
- let view = info.texture().source().index();
- mat.base_color = Some(glium_srgb_texture(facade, &images[view])?);
- }
+ // Occlusion (linear)
+ if let Some(info) = primitive.material().occlusion_texture() {
+ update_sampler(&mut mat, &info.texture());
+ let view = info.texture().source().index();
+ mat.occlusion = Some(glium_linear_texture(facade, &images[view])?);
+ }
- // Metallic-Roughness (linear)
- if let Some(info) = pbr.metallic_roughness_texture() {
- update_sampler(&mut mat, &info.texture());
- let view = info.texture().source().index();
- mat.metallic_roughness = Some(glium_linear_texture(facade, &images[view])?);
- }
+ // Emissive (sRGB)
+ if let Some(info) = primitive.material().emissive_texture() {
+ update_sampler(&mut mat, &info.texture());
+ let view = info.texture().source().index();
+ mat.emissive = Some(glium_srgb_texture(facade, &images[view])?);
+ }
- // Normal map (linear)
- if let Some(info) = material.normal_texture() {
- update_sampler(&mut mat, &info.texture());
- let view = info.texture().source().index();
- mat.normal = Some(glium_linear_texture(facade, &images[view])?);
- }
-
- // Occlusion (linear)
- if let Some(info) = material.occlusion_texture() {
- update_sampler(&mut mat, &info.texture());
- let view = info.texture().source().index();
- mat.occlusion = Some(glium_linear_texture(facade, &images[view])?);
- }
-
- // Emissive (sRGB)
- if let Some(info) = material.emissive_texture() {
- update_sampler(&mut mat, &info.texture());
- let view = info.texture().source().index();
- mat.emissive = Some(glium_srgb_texture(facade, &images[view])?);
- }
-
- // KHR_texture_transform (base color only, for now)
- if let Some(tex) = pbr.base_color_texture() {
- if let Some(xform) = tex.texture_transform() {
- mat.uv_offset = Vec2::new(xform.offset()[0], xform.offset()[1]);
- mat.uv_scale = Vec2::new(xform.scale()[0], xform.scale()[1]);
- }
- }
-
- // ---- Vertex/index data ----
- let reader = primitive.reader(|buf| Some(&buffers[buf.index()].0));
-
- let positions: Vec<[f32; 3]> = reader.read_positions().context("missing POSITION")?.collect();
- let normals: Vec<[f32; 3]> = reader.read_normals().context("missing NORMAL")?.collect();
- let tex_coords: Vec<[f32; 2]> = reader
- .read_tex_coords(0)
- .map(|tc| tc.into_f32().collect())
- .unwrap_or_else(|| vec![[0.0, 0.0]; positions.len()]);
- let indices: Vec = reader.read_indices().context("missing indices")?.into_u32().collect();
-
- // Interleave
- let vertices: Vec = (0..positions.len())
- .map(|i| Vertex { position: positions[i], normal: normals[i], tex_coords: tex_coords[i] })
- .collect();
-
- let vbuf = VertexBuffer::immutable(facade, &vertices)?;
- let ibuf = IndexBuffer::immutable(facade, PrimitiveType::TrianglesList, &indices)?;
-
- out.push(Model { mesh: Mesh { vbuf, ibuf }, material: mat });
+ // KHR_texture_transform
+ if let Some(tex) = pbr.base_color_texture() {
+ if let Some(xform) = tex.texture_transform() {
+ mat.uv_offset = Vec2::new(xform.offset()[0], xform.offset()[1]);
+ mat.uv_scale = Vec2::new(xform.scale()[0], xform.scale()[1]);
}
}
- if out.is_empty() {
- bail!("glTF has no mesh primitives");
- }
+ // ---- Vertex/index data ----
+ let reader = primitive.reader(|buf| Some(&buffers[buf.index()].0));
- Ok(out)
+ let positions: Vec<[f32; 3]> = reader.read_positions().context("missing POSITION")?.collect();
+ let normals: Vec<[f32; 3]> = reader.read_normals().context("missing NORMAL")?.collect();
+ let tex_coords: Vec<[f32; 2]> = reader.read_tex_coords(0).map(|tc| tc.into_f32().collect()).unwrap_or_else(|| vec![[0.0, 0.0]; positions.len()]);
+ let indices: Vec = reader.read_indices().context("missing indices")?.into_u32().collect();
+
+ // Interleave
+ let vertices: Vec = (0..positions.len()).map(|i| Vertex { position: positions[i], normal: normals[i], tex_coords: tex_coords[i] }).collect();
+
+ let vbuf = VertexBuffer::immutable(facade, &vertices)?;
+ let ibuf = IndexBuffer ::immutable(facade, PrimitiveType::TrianglesList, &indices)?;
+
+ Ok(Model { mesh: Mesh { vbuf, ibuf }, material: mat })
}
/// Linear-space texture (RGBA8) from glTF image data.
diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs
index 8f00d92..db8e56e 100644
--- a/glium_platform/src/platform.rs
+++ b/glium_platform/src/platform.rs
@@ -1,7 +1,7 @@
-use std::cell::{RefCell, Cell};
+use std::cell::RefCell;
use std::rc::Rc;
-use std::sync::{Arc, Mutex, RwLock};
-use raidillon_platform::{Platform, PlatformContext, TimeContext, DebugWireframes, DebugWireframesRef};
+use std::sync::{Arc, Mutex};
+use raidillon_platform::{Platform, PlatformContext, TimeContext};
use glium::backend::glutin::Display;
use glium::backend::glutin::SimpleWindowBuilder;
use glium::glutin::surface::WindowSurface;
@@ -14,12 +14,11 @@ use raidillon_assets::ModelManagerRef;
use raidillon_core::engine::EngineTrait;
use raidillon_core::time;
use raidillon_core::time::Time;
-use crate::render::{BasicMeshRenderingSystem, DebugWireframeRenderingSystem, EguiRenderer, SkyboxRenderingSystem};
+use crate::render::debug_ui::ImguiBridge;
+use crate::render::{BasicMeshRenderingSystem, SkyboxRenderingSystem};
use crate::GliumAssetManager;
use glam::Vec3;
use winit::event::DeviceEvent::MouseMotion;
-use raidillon_core::EguiQueue;
-use raidillon_platform::settings::{Settings, default_config_path};
pub struct GliumPlatform> {
event_loop: EventLoop<()>,
@@ -29,10 +28,6 @@ pub struct GliumPlatform> {
asset_manager: ModelManagerRef,
engine: E,
time: time::Time,
- egui_queue: Rc>,
- settings: Arc>,
- debug_wireframes: DebugWireframesRef,
- should_egui_receive_input_events: Rc>,
}
impl> Platform for GliumPlatform {
@@ -55,20 +50,9 @@ impl> Platform for GliumPlatfor
let window = Arc::new(Mutex::new(window));
// Install rendering systems in order
- rendering_system_manager.add::(&display, window.clone(), &event_loop);
- rendering_system_manager.add::(&display, window.clone(), &event_loop);
- rendering_system_manager.add::(&display, window.clone(), &event_loop);
- rendering_system_manager.add::(&display, window.clone(), &event_loop);
-
- let egui_queue = Rc::new(RefCell::new(EguiQueue::new()));
-
- let settings = Arc::new(
- RwLock::new(
- Settings::load_or_default(default_config_path()).unwrap()
- )
- );
- let debug_wireframes = Rc::new(RefCell::new(DebugWireframes::new()));
- let should_egui_receive_input_events = Rc::new(Cell::new(false));
+ rendering_system_manager.add::(&display, window.clone());
+ rendering_system_manager.add::(&display, window.clone());
+ rendering_system_manager.add::(&display, window.clone());
Self {
event_loop,
@@ -78,10 +62,6 @@ impl> Platform for GliumPlatfor
asset_manager,
engine,
time,
- egui_queue,
- settings,
- debug_wireframes,
- should_egui_receive_input_events,
}
}
@@ -97,21 +77,9 @@ impl> Platform for GliumPlatfor
frame_height: h as f32,
time_ctx: self.construct_time_ctx(),
window: self.window.clone(),
- egui_queue: self.egui_queue.clone(),
- settings: self.settings.clone(),
- debug_wireframes: self.debug_wireframes.clone(),
- should_egui_receive_input_events: self.should_egui_receive_input_events.clone(),
};
self.engine.initialize(ctx.clone());
- self.settings.read().unwrap().display_settings.apply(&*self.window.lock().unwrap());
-
let _ = &self.event_loop.run(move |event, el| {
- let settings_handle = self.settings.read().unwrap();
- if settings_handle.display_settings.dirty {
- settings_handle.display_settings.apply(&*self.window.lock().unwrap());
- }
- drop(settings_handle);
-
self.rendering_system_manager
.systems
.values_mut()
@@ -123,30 +91,24 @@ impl> Platform for GliumPlatfor
match event {
Event::WindowEvent { event, .. } => match event {
- WindowEvent::Resized(size) => {
- if size.width > 0 && size.height > 0 {
- self.display.resize((size.width, size.height));
- }
- },
WindowEvent::CloseRequested => {
// TODO: Run uninitialize on renderer and engine
- self.settings.read().unwrap().save_to_file(default_config_path());
el.exit();
},
WindowEvent::RedrawRequested => {
let mut target = self.display.draw();
target.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0);
- let scene = self.engine.current_scene();
+ let (scene, debug_ui_buffer) = (
+ self.engine.current_scene(),
+ self.engine.get_debug_ui_buffer(),
+ );
let mut context = RenderingContext {
scene,
target: &mut target,
- display: &self.display,
asset_manager: self.asset_manager.clone(),
window: self.window.clone(),
- egui_queue: self.egui_queue.clone(),
- debug_wireframes: self.debug_wireframes.clone(),
+ debug_ui_buffer,
env_light_dir: Vec3::new(0.0, -1.0, 0.0),
- should_egui_receive_input_events: self.should_egui_receive_input_events.clone(),
};
self.rendering_system_manager
@@ -154,9 +116,6 @@ impl> Platform for GliumPlatfor
.values_mut()
.for_each(|system| system.render(&mut context));
- // clear debug wireframes after rendering
- self.debug_wireframes.borrow_mut().clear();
-
target.finish().unwrap();
}
_ => {},
diff --git a/glium_platform/src/render/basic.rs b/glium_platform/src/render/basic.rs
index 6553cc0..663b2dd 100644
--- a/glium_platform/src/render/basic.rs
+++ b/glium_platform/src/render/basic.rs
@@ -9,8 +9,6 @@ use raidillon_assets::include_shader;
pub use raidillon_platform::Camera;
use glam::Vec3;
use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction};
-use winit::event::Event;
-use winit::event_loop::EventLoop;
use raidillon_ecs::{Transform, ModelID};
use raidillon_ecs::components::ModelHandle;
use crate::model::Model;
@@ -23,7 +21,7 @@ pub struct BasicMeshRenderingSystem {
}
impl RenderingSystem for BasicMeshRenderingSystem {
- fn initialize(display: &Display, _window: Arc>, event_loop: &EventLoop<()>) -> Self {
+ fn initialize(display: &Display, _window: Arc>) -> Self {
const VERT_SRC: &str = include_shader!("gl_textured.vert");
const FRAG_SRC: &str = include_shader!("gl_textured.frag");
@@ -59,11 +57,7 @@ impl RenderingSystem for BasicMeshRenderingSystem {
};
// Use HDR-derived environment light direction if provided, otherwise default to downward
- let light_dir_world: Vec3 = if ctx.env_light_dir.length_squared() > 0.0 { ctx.env_light_dir.normalize() } else { Vec3::new(0.0, -1.0, 0.0) };
-
- // Transform light direction to view space (normals/positions are in view space)
- let view_mat3 = glam::Mat3::from_mat4(cam.view());
- let light_dir_view = (view_mat3 * light_dir_world).normalize();
+ let light_dir: Vec3 = if ctx.env_light_dir.length_squared() > 0.0 { ctx.env_light_dir.normalize() } else { Vec3::new(0.0, -1.0, 0.0) };
let asset_manager = ctx.asset_manager.borrow();
@@ -73,43 +67,41 @@ impl RenderingSystem for BasicMeshRenderingSystem {
_ => continue,
};
- let models = match model.downcast_ref::>() {
- Some(models) => models,
+ let model = match model.downcast_ref::() {
+ Some(model) => model,
None => continue,
};
- for model in models {
- let mesh = &model.mesh;
- let mat = &model.material;
+ let mesh = &model.mesh;
+ let mat = &model.material;
- let tex_ref: &SrgbTexture2d = mat.base_color.as_ref().unwrap_or(&self.white_tex);
+ let tex_ref: &SrgbTexture2d = mat.base_color.as_ref().unwrap_or(&self.white_tex);
- let mut sampler = tex_ref.sampled();
- sampler = sampler.wrap_function(SamplerWrapFunction::Repeat);
- sampler = sampler.minify_filter(MinifySamplerFilter::Linear);
- sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear);
+ let mut sampler = tex_ref.sampled();
+ sampler = sampler.wrap_function(SamplerWrapFunction::Repeat);
+ sampler = sampler.minify_filter(MinifySamplerFilter::Linear);
+ sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear);
- let c = mat.base_color_factor;
+ let c = mat.base_color_factor;
- let uniforms = uniform! {
- model: tr.matrix().to_cols_array_2d(),
- view: cam.view().to_cols_array_2d(),
- projection: cam.projection().to_cols_array_2d(),
- u_light: [light_dir_view.x, light_dir_view.y, light_dir_view.z],
- tex: sampler,
- color: [c[0], c[1], c[2]],
- uv_offset: [mat.uv_offset.x, mat.uv_offset.y],
- uv_scale: [mat.uv_scale.x, mat.uv_scale.y],
- };
+ let uniforms = uniform! {
+ model: tr.matrix().to_cols_array_2d(),
+ view: cam.view().to_cols_array_2d(),
+ projection: cam.projection().to_cols_array_2d(),
+ u_light: [light_dir.x, light_dir.y, light_dir.z],
+ tex: sampler,
+ color: [c[0], c[1], c[2]],
+ uv_offset: [mat.uv_offset.x, mat.uv_offset.y],
+ uv_scale: [mat.uv_scale.x, mat.uv_scale.y],
+ };
- ctx.target.draw(
- &mesh.vbuf,
- &mesh.ibuf,
- &self.program,
- &uniforms,
- &self.params,
- ).unwrap();
- }
+ ctx.target.draw(
+ &mesh.vbuf,
+ &mesh.ibuf,
+ &self.program,
+ &uniforms,
+ &self.params,
+ ).unwrap();
}
}
}
diff --git a/glium_platform/src/render/debug_ui.rs b/glium_platform/src/render/debug_ui.rs
new file mode 100644
index 0000000..ac4a06e
--- /dev/null
+++ b/glium_platform/src/render/debug_ui.rs
@@ -0,0 +1,75 @@
+use std::sync::{Arc, Mutex};
+use std::time::Instant;
+use glium::Display;
+use glium::glutin::surface::WindowSurface;
+use imgui::{Context as ImguiContext};
+use imgui_winit_support::{HiDpiMode, WinitPlatform};
+use imgui_glium_renderer::Renderer as ImguiGliumRenderer;
+use winit::window::Window;
+use winit::event::Event;
+use glium::Frame;
+use crate::RenderingSystem;
+use crate::system::RenderingContext;
+
+pub struct ImguiBridge {
+ imgui: ImguiContext,
+ platform: WinitPlatform,
+ renderer: ImguiGliumRenderer,
+ last_frame: Instant,
+ rendered_this_frame: bool,
+}
+
+impl RenderingSystem for ImguiBridge {
+ fn handle_event(&mut self, window: Arc>, event: Event<()>) {
+ let window = window.lock().unwrap();
+ self.platform.handle_event(self.imgui.io_mut(), &*window, &event);
+ }
+
+ fn prepare_frame(&mut self, window: Arc>) {
+ self.rendered_this_frame = false;
+ let now = Instant::now();
+ self.imgui.io_mut().update_delta_time(now - self.last_frame);
+ self.last_frame = now;
+ let window = window.lock().unwrap();
+ self.platform
+ .prepare_frame(self.imgui.io_mut(), &*window)
+ .expect("Failed to prepare frame");
+ }
+
+ fn render(&mut self, ctx: &mut RenderingContext) {
+ if self.rendered_this_frame { return; }
+ self.rendered_this_frame = true;
+
+ let ui = self.imgui.frame();
+ ctx.debug_ui_buffer.write_buffer(&ui);
+
+ {
+ let window = ctx.window.lock().unwrap();
+ self.platform.prepare_render(&ui, &*window);
+ }
+ let draw_data = self.imgui.render();
+ if draw_data.total_vtx_count == 0 && draw_data.total_idx_count == 0 {
+ return;
+ }
+
+ self.renderer.render(ctx.target, draw_data).expect("imgui rendering failed");
+ }
+
+ fn initialize(display: &Display, window: Arc>) -> Self {
+ let mut imgui = ImguiContext::create();
+ imgui.set_ini_filename(None);
+ let mut platform = WinitPlatform::new(&mut imgui);
+ let window = window.lock().unwrap();
+ platform.attach_window(imgui.io_mut(), &*window, HiDpiMode::Default);
+ imgui.fonts().add_font(&[imgui::FontSource::DefaultFontData { config: None }]);
+ let renderer = ImguiGliumRenderer::new(&mut imgui, display).unwrap();
+
+ Self {
+ imgui,
+ platform,
+ renderer,
+ last_frame: Instant::now(),
+ rendered_this_frame: false,
+ }
+ }
+}
diff --git a/glium_platform/src/render/debug_wireframe.rs b/glium_platform/src/render/debug_wireframe.rs
deleted file mode 100644
index 2f259e9..0000000
--- a/glium_platform/src/render/debug_wireframe.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-use std::sync::{Arc, Mutex};
-use glium::{Display, Program, Surface, VertexBuffer, implement_vertex};
-use glium::glutin::surface::WindowSurface;
-use glium::index::PrimitiveType;
-use glium::uniform;
-use winit::event_loop::EventLoop;
-use raidillon_assets::include_shader;
-use crate::system::RenderingContext;
-use crate::RenderingSystem;
-pub use raidillon_platform::Camera;
-
-#[derive(Copy, Clone)]
-struct DebugVertex {
- position: [f32; 3],
- color: [f32; 4],
-}
-
-implement_vertex!(DebugVertex, position, color);
-
-/// renders debug wireframes from the shared buffer
-pub struct DebugWireframeRenderingSystem {
- program: Program,
- params: glium::DrawParameters<'static>,
-}
-
-impl RenderingSystem for DebugWireframeRenderingSystem {
- fn initialize(display: &Display, _window: Arc>, _event_loop: &EventLoop<()>) -> Self {
- const VERT_SRC: &str = include_shader!("debug_wireframe.vert");
- const FRAG_SRC: &str = include_shader!("debug_wireframe.frag");
-
- let program = Program::from_source(display, VERT_SRC, FRAG_SRC, None).unwrap();
-
- let params = glium::DrawParameters {
- depth: glium::Depth {
- test: glium::draw_parameters::DepthTest::IfLess,
- write: false,
- ..Default::default()
- },
- line_width: Some(1.0),
- ..Default::default()
- };
-
- Self { program, params }
- }
-
- fn render(&mut self, ctx: &mut RenderingContext) {
- let debug_wireframes = ctx.debug_wireframes.borrow();
-
- if !debug_wireframes.enabled || debug_wireframes.vertices.is_empty() {
- return;
- }
-
- let cam = match ctx.scene.world.query::<&Camera>().iter().next() {
- Some((_, cam)) => *cam,
- None => return,
- };
-
- let vertices: Vec = debug_wireframes.vertices.iter()
- .map(|v| DebugVertex { position: v.position, color: v.color })
- .collect();
-
- let vbuf = match VertexBuffer::new(ctx.display, &vertices) {
- Ok(vb) => vb,
- Err(_) => return,
- };
-
- let uniforms = uniform! {
- view: cam.view().to_cols_array_2d(),
- projection: cam.projection().to_cols_array_2d(),
- };
-
- ctx.target.draw(
- &vbuf,
- glium::index::NoIndices(PrimitiveType::LinesList),
- &self.program,
- &uniforms,
- &self.params,
- ).ok();
- }
-}
diff --git a/glium_platform/src/render/egui.rs b/glium_platform/src/render/egui.rs
deleted file mode 100644
index 3cd0583..0000000
--- a/glium_platform/src/render/egui.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-use std::sync::{Arc, Mutex};
-use egui::ViewportId;
-use glium::{Display, Frame};
-use glium::glutin::surface::WindowSurface;
-use winit::window::Window;
-use crate::RenderingSystem;
-use crate::system::RenderingContext;
-use egui_glium::EguiGlium;
-use winit::event::{Event, WindowEvent};
-use winit::event_loop::EventLoop;
-use std::cell::Cell;
-use std::rc::Rc;
-
-pub struct EguiRenderer {
- egui_glium: EguiGlium,
- should_egui_receive_input_events: Option>>,
-}
-
-impl RenderingSystem for EguiRenderer {
- fn initialize(display: &Display, window: Arc>, event_loop: &EventLoop<()>) -> Self
- where
- Self: Sized,
- {
- let window = window.lock().unwrap();
- let egui_glium = EguiGlium::new(ViewportId::ROOT, &display, &window, &event_loop);
-
- Self { egui_glium: egui_glium, should_egui_receive_input_events: None }
- }
-
- fn render(&mut self, ctx: &mut RenderingContext) {
- if self.should_egui_receive_input_events.is_none() {
- self.should_egui_receive_input_events = Some(ctx.should_egui_receive_input_events.clone());
- }
-
- let window = ctx.window.lock().unwrap();
-
- self.egui_glium.run(&window, |egui_ctx| {
- ctx.egui_queue.borrow_mut().run(egui_ctx);
- });
-
- self.egui_glium.paint(ctx.display, ctx.target);
- }
-
- fn handle_event(&mut self, window: Arc>, event: Event<()>) {
- let window = window.lock().unwrap();
- match event {
- Event::WindowEvent { event, .. } => {
- let should_egui_receive_input_events = match self.should_egui_receive_input_events.as_ref() {
- Some(v) => v.get(),
- None => true,
- };
-
- let should_send_event = if should_egui_receive_input_events {
- true
- } else {
- !matches!(event,
- WindowEvent::KeyboardInput { .. } |
- WindowEvent::ModifiersChanged(_) |
- WindowEvent::CursorMoved { .. } |
- WindowEvent::MouseInput { .. } |
- WindowEvent::MouseWheel { .. } |
- WindowEvent::Touch(_) |
- WindowEvent::Ime(_)
- )
- };
-
- if should_send_event {
- let _ = self.egui_glium.on_event(&window, &event);
- }
- }
- _ => {},
- }
- }
-}
diff --git a/glium_platform/src/render/mod.rs b/glium_platform/src/render/mod.rs
index 22aa047..f49e308 100644
--- a/glium_platform/src/render/mod.rs
+++ b/glium_platform/src/render/mod.rs
@@ -1,9 +1,6 @@
mod basic;
+pub mod debug_ui;
mod skybox;
-mod egui;
-mod debug_wireframe;
pub use basic::BasicMeshRenderingSystem;
pub use skybox::SkyboxRenderingSystem;
-pub use egui::EguiRenderer;
-pub use debug_wireframe::DebugWireframeRenderingSystem;
diff --git a/glium_platform/src/render/skybox.rs b/glium_platform/src/render/skybox.rs
index d11683b..ac22210 100644
--- a/glium_platform/src/render/skybox.rs
+++ b/glium_platform/src/render/skybox.rs
@@ -7,9 +7,7 @@ use glium::glutin::surface::WindowSurface;
use glium::index::PrimitiveType;
use glium::texture::{RawImage2d, SrgbTexture2d, Texture2d};
use glium::uniform;
-use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction};
use glam::{Mat4, Vec2, Vec3};
-use winit::event_loop::EventLoop;
use raidillon_assets::include_shader;
use crate::system::RenderingContext;
use crate::RenderingSystem;
@@ -111,7 +109,7 @@ impl SkyboxRenderingSystem {
}
impl RenderingSystem for SkyboxRenderingSystem {
- fn initialize(display: &Display, _window: Arc>, event_loop: &EventLoop<()>) -> Self {
+ fn initialize(display: &Display, _window: Arc>) -> Self {
const VERT_SRC: &str = include_shader!("skybox.vert");
const FRAG_SRC: &str = include_shader!("skybox.frag");
let program = Program::from_source(display, VERT_SRC, FRAG_SRC, None).unwrap();
@@ -119,7 +117,7 @@ impl RenderingSystem for SkyboxRenderingSystem {
// Load EXR from assets/exr
let manifest_dir = env!("CARGO_MANIFEST_DIR");
- let path = std::path::Path::new(manifest_dir).join("../assets/exr/citrus_orchard_road_puresky_4k.exr");
+ let path = std::path::Path::new(manifest_dir).join("../assets/exr/qwantani_sunset_puresky_2k.exr");
let (equirect_srgb, light_dir) = Self::load_hdr_equirect_and_analyze(display, &path);
Self { program, quad_vb, quad_ib, equirect_srgb, light_dir }
}
@@ -133,15 +131,10 @@ impl RenderingSystem for SkyboxRenderingSystem {
let mut view = cam.view();
// remove translation from view matrix (only orientation)
view.col_mut(3).x = 0.0; view.col_mut(3).y = 0.0; view.col_mut(3).z = 0.0;
- let mut sampler = self.equirect_srgb.sampled();
- sampler = sampler.wrap_function(SamplerWrapFunction::Repeat);
- sampler = sampler.minify_filter(MinifySamplerFilter::Linear);
- sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear);
-
let uniforms = uniform! {
view: view.to_cols_array_2d(),
projection: cam.projection().to_cols_array_2d(),
- equirect: sampler,
+ equirect: &self.equirect_srgb,
};
let params = glium::DrawParameters { depth: glium::Depth { test: glium::draw_parameters::DepthTest::IfLessOrEqual, write: false, ..Default::default() }, ..Default::default() };
ctx.target.draw(&self.quad_vb, &self.quad_ib, &self.program, &uniforms, ¶ms).ok();
diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs
index cf5f945..51a292f 100644
--- a/glium_platform/src/system.rs
+++ b/glium_platform/src/system.rs
@@ -6,23 +6,17 @@ use indexmap::IndexMap;
use glium::{Display, Frame};
use glium::glutin::surface::WindowSurface;
use raidillon_assets::ModelManagerRef;
-use raidillon_core::{define_typemap, EguiQueue};
+use raidillon_core::{define_typemap, DebugUIBuffer};
use raidillon_core::scene::Scene;
-use raidillon_platform::DebugWireframesRef;
use glam::Vec3;
-use winit::event_loop::EventLoop;
-use std::cell::Cell;
pub struct RenderingContext<'a> {
pub scene: &'a Scene,
pub target: &'a mut Frame,
pub window: Arc>,
- pub display: &'a Display,
pub asset_manager: ModelManagerRef,
- pub egui_queue: Rc>,
- pub debug_wireframes: DebugWireframesRef,
+ pub debug_ui_buffer: &'a DebugUIBuffer,
pub env_light_dir: Vec3,
- pub should_egui_receive_input_events: Rc>
}
/// The internal "rendering system" trait of glium_platform.
@@ -36,7 +30,7 @@ pub trait RenderingSystem {
}
fn prepare_frame(&mut self, _window: Arc>) {}
fn render(&mut self, ctx: &mut RenderingContext);
- fn initialize(display: &Display, window: Arc>, event_loop: &EventLoop<()>) -> Self
+ fn initialize(display: &Display, window: Arc>) -> Self
where
Self: Sized;
}
@@ -54,11 +48,11 @@ impl RenderingSystemManager {
}
}
- pub fn add(&mut self, display: &Display, window: Arc>, event_loop: &EventLoop<()>)
+ pub fn add(&mut self, display: &Display, window: Arc>)
where
R: RenderingSystem + 'static,
{
- let system = R::initialize(display, window, event_loop);
+ let system = R::initialize(display, window);
self.systems.insert(TypeId::of::(), Box::new(system));
}
diff --git a/platform/Cargo.toml b/platform/Cargo.toml
index 16fec56..3b42bac 100644
--- a/platform/Cargo.toml
+++ b/platform/Cargo.toml
@@ -8,5 +8,3 @@ winit = "0.30.12"
raidillon_core = { path = "../core" }
raidillon_assets = { path = "../asset" }
glam = "0.30.5"
-serde = { version = "1.0.228", features = ["derive"] }
-toml = "0.9.8"
diff --git a/platform/src/context.rs b/platform/src/context.rs
index 31bd6cb..892b69e 100644
--- a/platform/src/context.rs
+++ b/platform/src/context.rs
@@ -1,66 +1,6 @@
-use std::cell::Cell;
-use std::{cell::RefCell, rc::Rc};
-use std::sync::{Arc, Mutex, RwLock};
+use std::sync::{Arc, Mutex};
use winit::event::Event;
use raidillon_assets::ModelManagerRef;
-use raidillon_core::EguiQueue;
-use crate::settings::Settings;
-
-/// a single debug wireframe vertex with position and color
-#[derive(Clone, Copy)]
-pub struct DebugWireframeVertex {
- pub position: [f32; 3],
- pub color: [f32; 4],
-}
-
-/// shared buffer for debug wireframe rendering
-#[derive(Clone, Default)]
-pub struct DebugWireframes {
- pub vertices: Vec,
- pub enabled: bool,
-}
-
-impl DebugWireframes {
- pub fn new() -> Self {
- Self { vertices: Vec::new(), enabled: true }
- }
-
- pub fn clear(&mut self) {
- self.vertices.clear();
- }
-
- /// add a single line segment
- pub fn add_line(&mut self, start: [f32; 3], end: [f32; 3], color: [f32; 4]) {
- self.vertices.push(DebugWireframeVertex { position: start, color });
- self.vertices.push(DebugWireframeVertex { position: end, color });
- }
-
- /// add a wireframe box from min/max corners
- pub fn add_box(&mut self, min: [f32; 3], max: [f32; 3], color: [f32; 4]) {
- let [x0, y0, z0] = min;
- let [x1, y1, z1] = max;
-
- // bottom face edges
- self.add_line([x0, y0, z0], [x1, y0, z0], color);
- self.add_line([x1, y0, z0], [x1, y0, z1], color);
- self.add_line([x1, y0, z1], [x0, y0, z1], color);
- self.add_line([x0, y0, z1], [x0, y0, z0], color);
-
- // top face edges
- self.add_line([x0, y1, z0], [x1, y1, z0], color);
- self.add_line([x1, y1, z0], [x1, y1, z1], color);
- self.add_line([x1, y1, z1], [x0, y1, z1], color);
- self.add_line([x0, y1, z1], [x0, y1, z0], color);
-
- // vertical edges
- self.add_line([x0, y0, z0], [x0, y1, z0], color);
- self.add_line([x1, y0, z0], [x1, y1, z0], color);
- self.add_line([x1, y0, z1], [x1, y1, z1], color);
- self.add_line([x0, y0, z1], [x0, y1, z1], color);
- }
-}
-
-pub type DebugWireframesRef = Rc>;
#[derive(Clone)]
pub struct PlatformContext {
@@ -70,12 +10,6 @@ pub struct PlatformContext {
pub frame_height: f32,
pub time_ctx: TimeContext,
pub window: Arc>,
- pub egui_queue: Rc>,
- pub settings: Arc>,
- /// shared debug wireframe buffer
- pub debug_wireframes: DebugWireframesRef,
- /// sets whether or not egui will receive input events
- pub should_egui_receive_input_events: Rc| >,
}
#[derive(Clone)]
diff --git a/platform/src/lib.rs b/platform/src/lib.rs
index ef88e08..8875d35 100644
--- a/platform/src/lib.rs
+++ b/platform/src/lib.rs
@@ -2,8 +2,7 @@ pub mod platform;
mod camera;
mod event;
pub mod context;
-pub mod settings;
pub use platform::Platform;
pub use camera::Camera;
-pub use context::{PlatformContext, TimeContext, DebugWireframes, DebugWireframesRef, DebugWireframeVertex};
+pub use context::{PlatformContext, TimeContext};
diff --git a/platform/src/settings.rs b/platform/src/settings.rs
deleted file mode 100644
index a901137..0000000
--- a/platform/src/settings.rs
+++ /dev/null
@@ -1,166 +0,0 @@
-use winit::monitor::{MonitorHandle, VideoModeHandle};
-use winit::window::{Fullscreen, Window};
-use serde::{Serialize, Deserialize};
-use std::error::Error;
-use std::fs;
-use std::io;
-use std::path::{Path, PathBuf};
-
-pub fn default_config_path() -> PathBuf {
- let exe_path = std::env::current_exe().unwrap();
- let exe_dir = exe_path
- .parent()
- .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "executable has no parent")).unwrap();
-
- exe_dir.join("settings.toml")
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
-#[serde(rename_all = "snake_case")]
-pub enum WindowMode {
- BorderlessFullscreen,
- ExclusiveFullscreen,
- #[default]
- Windowed,
-}
-
-#[derive(Debug, Default, Serialize, Deserialize)]
-pub struct Settings {
- pub display_settings: DisplaySettings,
-}
-
-impl Settings {
- pub fn load_from_file(path: impl AsRef) -> Result> {
- let path = path.as_ref();
- let text = fs::read_to_string(path)?;
- let settings: Settings = toml::from_str(&text)?;
- Ok(settings)
- }
-
- pub fn save_to_file(&self, path: impl AsRef) -> Result<(), Box> {
- let path = path.as_ref();
- if let Some(parent) = path.parent() {
- fs::create_dir_all(parent)?;
- }
- let toml_str = toml::to_string_pretty(self)?;
- fs::write(path, toml_str)?;
- Ok(())
- }
-
- pub fn load_or_default(path: impl AsRef) -> Result> {
- let path = path.as_ref();
-
- match fs::read_to_string(path) {
- Ok(text) => {
- let settings: Settings = toml::from_str(&text)?;
- Ok(settings)
- }
- Err(err) if err.kind() == io::ErrorKind::NotFound => {
- let settings = Settings::default();
- if let Some(parent) = path.parent() {
- fs::create_dir_all(parent)?;
- }
- let toml_str = toml::to_string_pretty(&settings)?;
- fs::write(path, toml_str)?;
- Ok(settings)
- }
- Err(err) => Err(Box::new(err)),
- }
- }
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(default)]
-pub struct DisplaySettings {
- pub fullscreen_mode: WindowMode,
- #[serde(skip)]
- pub dirty: bool,
-}
-
-impl Default for DisplaySettings {
- fn default() -> Self {
- Self {
- fullscreen_mode: WindowMode::Windowed,
- dirty: false,
- }
- }
-}
-
-impl DisplaySettings {
- pub fn apply(&self, window: &Window) {
- // apply fullscreen mode
- match self.fullscreen_mode {
- WindowMode::BorderlessFullscreen => {
- let monitor = window.current_monitor().or_else(|| window.primary_monitor());
- window.set_fullscreen(Some(Fullscreen::Borderless(monitor)));
- }
- WindowMode::ExclusiveFullscreen => {
- let monitor = window.current_monitor().or_else(|| window.primary_monitor());
- match monitor {
- Some(monitor) => {
- if let Some(video_mode) = pick_best_video_mode(&monitor) {
- window.set_fullscreen(Some(Fullscreen::Exclusive(video_mode)));
- } else {
- // fallback to borderless
- window.set_fullscreen(Some(Fullscreen::Borderless(Some(monitor))));
- }
- }
- None => {
- // no monitor info, fallback to windowed
- window.set_fullscreen(None);
- }
- }
- }
- WindowMode::Windowed => {
- window.set_fullscreen(None);
- },
- }
- }
-}
-
-fn pick_best_video_mode(monitor: &MonitorHandle) -> Option {
- let target_size = monitor.size();
-
- let mut best_native: Option = None;
- let mut best_any: Option = None;
-
- for mode in monitor.video_modes() {
- if mode.size() == target_size {
- let replace = match best_native.as_ref() {
- None => true,
- Some(best) => {
- (mode.refresh_rate_millihertz(), mode.bit_depth())
- > (best.refresh_rate_millihertz(), best.bit_depth())
- }
- };
- if replace {
- best_native = Some(mode.clone());
- }
- }
-
- let replace = match best_any.as_ref() {
- None => true,
- Some(best) => is_better_video_mode(&mode, best),
- };
- if replace {
- best_any = Some(mode);
- }
- }
-
- best_native.or(best_any)
-}
-
-fn is_better_video_mode(a: &VideoModeHandle, b: &VideoModeHandle) -> bool {
- let a_size = a.size();
- let b_size = b.size();
- let a_area = u64::from(a_size.width) * u64::from(a_size.height);
- let b_area = u64::from(b_size.width) * u64::from(b_size.height);
-
- match a_area.cmp(&b_area) {
- std::cmp::Ordering::Greater => true,
- std::cmp::Ordering::Less => false,
- std::cmp::Ordering::Equal => {
- (a.refresh_rate_millihertz(), a.bit_depth()) > (b.refresh_rate_millihertz(), b.bit_depth())
- }
- }
-}
| | |