diff --git a/src/graphics/colormap/linear.rs b/src/graphics/colormap/linear.rs index bcc7de6..abd0621 100644 --- a/src/graphics/colormap/linear.rs +++ b/src/graphics/colormap/linear.rs @@ -98,6 +98,14 @@ impl ColorMap for LinearColormap { Ok(()) } + fn destroy(&mut self, gl: &glow::Context) { + unsafe { + if let Some(texture) = self.texture { + gl.delete_texture(texture); + } + } + } + fn bind_texture(&self, gl: &glow::Context, program: &Program) -> crate::errors::Result<()> { unsafe { gl.active_texture(glow::TEXTURE0); diff --git a/src/graphics/colormap/mod.rs b/src/graphics/colormap/mod.rs index 9587ef7..5363e29 100644 --- a/src/graphics/colormap/mod.rs +++ b/src/graphics/colormap/mod.rs @@ -12,4 +12,6 @@ pub trait ColorMap { fn bind_texture(&self, gl: &glow::Context, program: &Program) -> crate::errors::Result<()>; fn snippet_ref(&self) -> &crate::components::Snippet; + + fn destroy(&mut self, gl: &glow::Context); } diff --git a/src/graphics/mod.rs b/src/graphics/mod.rs index e2537f0..73d45ea 100644 --- a/src/graphics/mod.rs +++ b/src/graphics/mod.rs @@ -9,6 +9,7 @@ pub mod ty; use crate::{components::Program, errors::*}; pub use colormesh::ColorMesh; +use imgui::TextureId; pub trait Graphics { fn draw(&self, gl: &glow::Context) -> Result<()>; @@ -26,3 +27,10 @@ pub trait AttaWithBuffer { type Data; fn attach_with_buffer(&mut self, gl: &glow::Context, data: &Self::Data) -> Result<()>; } + + +pub trait AttaWithWindow { + + fn attach_with_window(&mut self, gl: &glow::Context) -> Result; + +} \ No newline at end of file diff --git a/src/graphics/ppi.rs b/src/graphics/ppi.rs index cc59e73..4911d55 100644 --- a/src/graphics/ppi.rs +++ b/src/graphics/ppi.rs @@ -1,5 +1,8 @@ +use std::cell::RefCell; +use std::rc::Rc; + use bytemuck::cast_slice; -use glow::{HasContext, NativeBuffer, NativeVertexArray}; +use glow::{HasContext, NativeBuffer, NativeFramebuffer, NativeTexture, NativeVertexArray}; use ndarray::{s, IndexLonger}; use crate::components::{CodeType, Program, Shader, Snippet}; @@ -9,21 +12,23 @@ use crate::errors::*; use super::colormap::ColorMap; use super::transforms::viewport::Viewport; use super::transforms::Transform; -use super::{ty, AttaWithBuffer, Graphics}; +use super::{ty, AttaWithBuffer, AttaWithWindow, Graphics}; -pub struct PPI<'a> { +pub struct PPI { program: Program, layer: isize, vao: Option, vbo: Option, - cmap: &'a mut dyn ColorMap, + cmap: Option>, + framebuffer: Option, + frametexture: Option, buffer: Vec<[f32; 3]>, } -impl<'a> PPI<'a> { - pub fn new(cmap: &'a mut dyn ColorMap) -> Result { +impl PPI { + pub fn new() -> Result { let vertex = Shader::new( glow::VERTEX_SHADER, CodeType::::Path("ppi.vert".into()), @@ -39,9 +44,7 @@ impl<'a> PPI<'a> { CodeType::::Path("ppi.frag".into()), )?; - let mut program = Program::new(vertex, fragment, Some(geom), "330 core"); - - program.set_hook("colormap", cmap.snippet_ref()); + let program = Program::new(vertex, fragment, Some(geom), "330 core"); Ok(Self { program, @@ -49,7 +52,9 @@ impl<'a> PPI<'a> { vao: None, vbo: None, buffer: Vec::with_capacity(180 * 50), - cmap, + framebuffer: None, + frametexture: None, + cmap: None, }) } @@ -61,9 +66,9 @@ impl<'a> PPI<'a> { self.program.set_viewport(viewport); } - pub fn set_colormap(&mut self, colormap: &'a mut dyn ColorMap) { - self.cmap = colormap; - // self.program.set_hook("colormap", colormap.snippet_ref()); + pub fn set_colormap(&mut self, colormap: Box) { + self.program.set_hook("colormap", colormap.snippet_ref()); + self.cmap = Some(colormap); } pub fn program(&mut self) -> &mut Program { @@ -165,10 +170,13 @@ fn max_step(data: &Vec) -> f32 { return max_gap; } -impl<'a> Graphics for PPI<'a> { +impl Graphics for PPI { fn compile(&mut self, gl: &glow::Context) -> Result<()> { self.program.compile(gl)?; - self.cmap.attach_with_program(gl, &self.program)?; + self.cmap + .as_mut() + .unwrap() + .attach_with_program(gl, &self.program)?; unsafe { let vao = gl.create_vertex_array().unwrap(); gl.bind_vertex_array(Some(vao)); @@ -199,6 +207,9 @@ impl<'a> Graphics for PPI<'a> { unsafe { self.vao.map(|vao| gl.delete_vertex_array(vao)); self.vbo.map(|vbo| gl.delete_buffer(vbo)); + self.framebuffer.map(|fb| gl.delete_framebuffer(fb)); + self.frametexture.map(|ft| gl.delete_texture(ft)); + self.cmap.as_mut().unwrap().destroy(gl); } Ok(()) @@ -208,11 +219,37 @@ impl<'a> Graphics for PPI<'a> { unsafe { gl.clear(glow::COLOR_BUFFER_BIT); gl.use_program(Some(self.program.native_program.unwrap())); - self.cmap.bind_texture(gl, &self.program)?; + self.cmap + .as_ref() + .unwrap() + .bind_texture(gl, &self.program)?; + + if self.framebuffer.is_some() { + gl.bind_framebuffer(glow::FRAMEBUFFER, self.framebuffer); + } + gl.depth_mask(false); gl.bind_vertex_array(Some(self.vao.unwrap())); gl.draw_arrays(glow::POINTS, 0, self.buffer.len() as i32); gl.depth_mask(true); + + if self.framebuffer.is_some() { + gl.framebuffer_texture_2d( + glow::FRAMEBUFFER, + glow::COLOR_ATTACHMENT0, + glow::TEXTURE_2D, + self.frametexture, + 0, + ); + + assert_eq!( + gl.check_framebuffer_status(glow::FRAMEBUFFER), + glow::FRAMEBUFFER_COMPLETE + ); + gl.bind_texture(glow::TEXTURE_2D, None); + gl.bind_framebuffer(glow::FRAMEBUFFER, None); + } + gl.bind_vertex_array(None); gl.use_program(None); } @@ -220,7 +257,7 @@ impl<'a> Graphics for PPI<'a> { } } -impl<'a> AttaWithBuffer for PPI<'a> { +impl AttaWithBuffer for PPI { type Data = Data; fn attach_with_buffer(&mut self, gl: &glow::Context, data: &Self::Data) -> Result<()> { @@ -242,6 +279,51 @@ impl<'a> AttaWithBuffer for PPI<'a> { } } +impl AttaWithWindow for PPI { + fn attach_with_window(&mut self, gl: &glow::Context) -> Result { + unsafe { + if self.framebuffer.is_none() { + let framebuffer = gl.create_framebuffer().unwrap(); + gl.bind_framebuffer(glow::FRAMEBUFFER, Some(framebuffer)); + + let texture = gl.create_texture().unwrap(); + + gl.bind_texture(glow::TEXTURE_2D, Some(texture)); + gl.tex_image_2d( + glow::TEXTURE_2D, + 0, + glow::RGB8 as i32, + 800, + 600, + 0, + glow::RGB, + glow::UNSIGNED_BYTE, + None, + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MIN_FILTER, + glow::LINEAR as i32, + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MAG_FILTER, + glow::LINEAR as i32, + ); + + gl.bind_framebuffer(glow::FRAMEBUFFER, None); + gl.bind_texture(glow::TEXTURE_2D, None); + self.frametexture = Some(texture); + Ok(imgui::TextureId::from(texture.0.get() as usize)) + } else { + Ok(imgui::TextureId::from( + self.frametexture.unwrap().0.get() as usize + )) + } + } + } +} + mod test { #[test] fn test_ppi() { diff --git a/src/main.rs b/src/main.rs index 9c993ea..cef3258 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,12 @@ +use std::cell::RefCell; +use std::rc::Rc; + use data_loader::Data; -use graphics::AttaWithBuffer; +use graphics::colormap::linear::LinearColormap; +use graphics::ppi::PPI; +use graphics::transforms::position::Position; +use graphics::transforms::viewport::Viewport; +use graphics::{AttaWithBuffer, Graphics, AttaWithWindow}; use imgui::Condition; mod camera; @@ -9,45 +16,68 @@ mod errors; mod graphics; mod support; mod utils; +use imgui::*; mod final_pg; fn main() { env_logger::init(); - let choices = ["test test this is 1", "test test this is 2"]; - let path = "/Users/tsuki/Desktop/ZJSXAA_20230113070200_R.dat.gz"; - let data = Data::from_path(path).unwrap(); - let mut value = 0; - support::supporter::init(move |_, ui, program, window, gl| { - ui.window("Hello world") - .size([300.0, 110.0], Condition::FirstUseEver) - .build(|| { - ui.text_wrapped("Hello world!"); - ui.text_wrapped("こんにちは世界!"); - if ui.button(choices[value]) { - value += 1; - value %= 2; - } - ui.button("This...is...imgui-rs!"); - ui.separator(); - let mouse_pos = ui.io().mouse_pos; - ui.text(format!( - "Mouse Position: ({:.1},{:.1})", - mouse_pos[0], mouse_pos[1] - )); + let transform = Position::new().unwrap(); + let mut viewport = Viewport::new().unwrap(); + viewport.set_global(0.0, 0.0, 600.0, 800.0); - if ui.button("Add Layer") { - program.add_ppi_layer(1); - program.attach_with_buffer(gl, &data).unwrap(); - window.request_redraw(); - } + let mut cmap = LinearColormap::new().unwrap(); - if ui.button("Remove Layer") { - program.add_ppi_layer(-1); - program.attach_with_buffer(gl, &data).unwrap(); - window.request_redraw(); - } - }); - }); -} + cmap.set_colors(vec![ + [170, 170, 170, 255], + [0, 34, 255, 255], + [1, 160, 246, 255], + [0, 236, 236, 255], + [0, 216, 0, 255], + [1, 144, 0, 255], + [255, 255, 0, 255], + [231, 192, 0, 255], + [255, 144, 0, 255], + [255, 0, 0, 255], + [214, 0, 0, 255], + [192, 0, 0, 255], + [255, 0, 240, 255], + [150, 0, 180, 255], + ]); + + cmap.set_range(0.0, 70.0); + + let mut ppi = PPI::new().unwrap(); + ppi.set_transform(&transform); + ppi.set_viewport(&viewport); + ppi.set_colormap(Box::new(cmap)); + + let ppi = Rc::new(RefCell::new(ppi)); + + let registers = vec![ppi.clone()]; + let registers = registers.into_iter().map(|r| { + r as Rc> + }).collect(); + + + support::supporter::init(move |run, ui, window, gl| { + let mut ppi = ppi.borrow_mut(); + let texture = ppi.attach_with_window(gl).unwrap(); + + ui.window("test").build(||{ + if ui.button("load") { + let data = Data::from_path(r#"C:\Users\qwin7\Downloads\ZJSXAA_20230113070200_R.dat.gz"#).unwrap(); + ppi.attach_with_buffer(gl, &data).unwrap(); + } + }); + + ui.window("Test").size([200.0,400.0], imgui::Condition::FirstUseEver).build(|| { + imgui::Image::new(texture, [200.0, 400.0]).build(ui); + }); + + + }, + registers, +); +} \ No newline at end of file diff --git a/src/support/supporter.rs b/src/support/supporter.rs index 154a7ab..1f3b67f 100644 --- a/src/support/supporter.rs +++ b/src/support/supporter.rs @@ -32,12 +32,14 @@ use imgui_winit_support::{ use nalgebra_glm::perspective; use nalgebra_glm::Vec3; use raw_window_handle::HasRawWindowHandle; +use std::cell::RefCell; use std::num::NonZeroU32; +use std::rc::Rc; use std::time::Instant; -pub fn init(mut run_ui: FUi) +pub fn init(mut run_ui: FUi, mut register: Vec>>) where - FUi: FnMut(&mut bool, &mut Ui, &mut PPI, &Window, &glow::Context) + 'static, + FUi: FnMut(&mut bool, &mut Ui, &Window, &glow::Context) + 'static, { let (event_loop, window, surface, context) = create_window(); let (mut winit_platform, mut imgui_context) = imgui_init(&window); @@ -53,39 +55,13 @@ where // OpenGL renderer from this crate let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context) .expect("failed to create renderer"); + let gl_context = ig_renderer.gl_context().clone(); + for r in register.iter_mut() { + r.borrow_mut().compile(&gl_context).unwrap(); + } + let mut last_frame = Instant::now(); - let transform = Position::new().unwrap(); - - let mut viewport = Viewport::new().unwrap(); - let mut cmap = LinearColormap::new().unwrap(); - - cmap.set_colors(vec![ - [170, 170, 170, 255], - [0, 34, 255, 255], - [1, 160, 246, 255], - [0, 236, 236, 255], - [0, 216, 0, 255], - [1, 144, 0, 255], - [255, 255, 0, 255], - [231, 192, 0, 255], - [255, 144, 0, 255], - [255, 0, 0, 255], - [214, 0, 0, 255], - [192, 0, 0, 255], - [255, 0, 240, 255], - [150, 0, 180, 255], - ]); - cmap.set_range(0.0, 70.0); - - let mut ppi = PPI::new(&mut cmap).unwrap(); - ppi.set_transform(&transform); - ppi.set_viewport(&viewport); - ppi.compile(ig_renderer.gl_context()).unwrap(); - - transform - .attach_with_program(ig_renderer.gl_context(), ppi.program_ref()) - .unwrap(); event_loop .run(move |event, window_target| { @@ -112,27 +88,25 @@ where // context from the `AutoRenderer`, which takes ownership of it. unsafe { - let gl = ig_renderer.gl_context(); - gl.clear(glow::DEPTH_BUFFER_BIT); + gl_context.clear(glow::DEPTH_BUFFER_BIT); + gl_context.clear(glow::COLOR_BUFFER_BIT); } - ppi.draw(ig_renderer.gl_context()).unwrap(); + let ui = imgui_context.frame(); + if ui.is_mouse_pos_valid(ui.io().mouse_pos) { let mouse_pos = ui.io().mouse_pos; if ui.is_mouse_dragging(imgui::MouseButton::Right) { - // mouse_callback( - // &mut last_position, - // PhysicalPosition::new(mouse_pos[0] as f64, mouse_pos[1] as f64), - // 0.05, - // &mut pitch, - // &mut yaw, - // &mut camera, - // ); } } + for r in register.iter_mut() { + r.borrow_mut().draw(&gl_context).unwrap(); + } + let mut run = true; - run_ui(&mut run, ui, &mut ppi, &window, ig_renderer.gl_context()); + + run_ui(&mut run, ui, &window, ig_renderer.gl_context()); if !run { window_target.exit(); @@ -167,22 +141,15 @@ where NonZeroU32::new(new_size.height).unwrap(), ); - viewport.set_global( - 0f32, - 0f32, - new_size.width as f32, - new_size.height as f32, - ); - - viewport - .attach_with_program(ig_renderer.gl_context(), ppi.program_ref()) - .unwrap(); } winit_platform.handle_event(imgui_context.io_mut(), &window, &event); } winit::event::Event::LoopExiting => { - let gl = ig_renderer.gl_context(); - ppi.destroy(gl).unwrap(); + + for r in register.iter_mut() { + r.borrow_mut().destroy(&gl_context).unwrap(); + } + } event => { winit_platform.handle_event(imgui_context.io_mut(), &window, &event);