1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
use super::{ProgramSettings, GLSL_VERSION, default_settings, fbo}; use rin_gl::{self as gl, uniforms, Renderer3d}; use rin_util::{Result, Error, LogErr}; use std::{io::Read, path::{Path, PathBuf}, rc::Rc}; use rin_graphics::Vertex2DTex; use std::cell::{Cell, RefCell}; use rin_events::{Property, ParamsDefault}; #[cfg(gui)] use rin_gui::ParameterGroup; #[cfg(glsl_debug)] use rin_util::AutoLoader; pub struct Lut { lut_path: RefCell<PathBuf>, size: Cell<f32>, texture_lut: RefCell<Option<gl::Texture>>, program: gl::Program, fbo: Rc<gl::Fbo>, #[cfg(glsl_debug)] loader: AutoLoader<gl::Program>, fullscreen_quad: Rc<gl::SimpleVao<Vertex2DTex>> } fn program_settings() -> ProgramSettings { ProgramSettings{ version: GLSL_VERSION, precision: gl::program::ShaderPrecision::High, extensions: vec![], defines: vec![], shaders: vec![ (gl::VERTEX_SHADER, shader!("shaders/full_quad.vs.glsl")), (gl::FRAGMENT_SHADER, shader!("shaders/lut.frag")), ], .. default_settings() } } #[derive(ParamsDefault, Clone, Debug)] #[cfg_attr(gui, derive(ParameterGroup))] pub struct LutParameters { #[cfg_attr(gui, gui(style{ extension: "cube" }))] path: Property<'static, PathBuf>, } impl Lut { pub fn new(gl: &gl::Renderer, w: u32, h: u32, format: gl::fbo::ColorFormat, fullscreen_quad: Rc<gl::SimpleVao<Vertex2DTex>>) -> Result<Lut> { #[cfg(glsl_debug)] let mut loader = gl.new_auto_program(program_settings()); let program; #[cfg(glsl_debug)] { program = loader.load().map_err(|err| Error::with_cause("Loading lut program", err))?; } #[cfg(not(glsl_debug))] { program = gl.new_program().from_settings(program_settings()) .log_err("") .map_err(|err| Error::with_cause("Loading Lut program", err))?; } let fbo = fbo(gl, w, h, format)?; Ok(Lut{ size: Cell::new(0.), texture_lut: RefCell::new(None), lut_path: RefCell::new(PathBuf::new()), fbo: Rc::new(fbo), #[cfg(glsl_debug)] loader, program, fullscreen_quad, }) } fn load_lut<P: AsRef<Path>>(&self, path: P, gl: &gl::Renderer) -> Result<()> { if path.as_ref().to_str().unwrap() == "" { *self.texture_lut.borrow_mut() = None; self.size.set(0.); Ok(()) }else{ if !path.as_ref().exists() || !path.as_ref().is_file() { return Err(Error::new("Path is not a file")) } let file = std::fs::File::open(&path) .map_err(|err| Error::with_cause("Loading Lut from .cube", err))?; let mut file = std::io::BufReader::new(file); let mut lutdata = String::new(); file.read_to_string(&mut lutdata) .map_err(|err| Error::with_cause("Reading Lut from .cube", err))?; let lut: lut_parser::CubeLut<f32> = lut_parser::CubeLut::from_str(&lutdata).unwrap(); if lut.kind == lut_parser::LutKind::Three { let mut texture_lut = gl.new_texture().from_format(gl::texture::Format::new_3d( gl::RGB32F, lut.size as u32, lut.size as u32, lut.size as u32, )).map_err(|err| Error::with_cause("Creating lut texture", err))?; texture_lut .load_data(lut.flatten_data(), Default::default()) .map_err(|err| Error::with_cause("Loading lut texture data", err))?; self.size.set(lut.size as f32); *self.texture_lut.borrow_mut() = Some(texture_lut); println!("Loaded {} size {}", path.as_ref().display(), lut.size); Ok(()) }else{ Err(Error::new("Can't parse One lut files yet")) } } } #[cfg(glsl_debug)] pub fn update(&mut self) { match self.loader.update(){ Ok(Some(program)) => { self.program = program; println!("lut shader reloaded correctly"); } Err(err) => { println!("{}", err); } _ => {} } } pub fn process<'a>(&'a self, gl: &gl::Renderer, source: &'a gl::Texture, parameters: &LutParameters) -> &gl::Texture { #[cfg(gl_debug_groups)] let _debug_group = gl.new_debug_group(0, "Look up table"); let path = parameters.path.get(); if path != &*self.lut_path.borrow() { let _ = self.load_lut(path, gl).log_err(""); *self.lut_path.borrow_mut() = path.clone(); } if let Some(lut) = self.texture_lut.borrow().as_ref() { let uniforms = uniforms! { source: (source, 1), lut: (lut, 2), lut_size: self.size.get(), }; gl.with_fbo(&*self.fbo) .draw_vao(&*self.fullscreen_quad, &self.program, &uniforms); self.fbo.color_tex(0).unwrap() }else{ source } } pub fn fbo(&self) -> &Rc<gl::Fbo> { &self.fbo } pub fn is_loaded(&self) -> bool { self.texture_lut.borrow().is_some() } }