diff --git a/examples/al-aas225.html b/examples/al-aas225.html index df6993b77..920782877 100644 --- a/examples/al-aas225.html +++ b/examples/al-aas225.html @@ -16,9 +16,9 @@ simbad.addSources([A.marker(204.97010833333336, 0.8400166666666667, {popupTitle: 'NGC 5257', popupDesc: 'Object type: HII galaxy
Morphological type: Sbc

More info in Simbad'}), A.marker(204.9903125, 0.8309694444444445, {popupTitle: 'NGC 5258', popupDesc: 'Object type: Galaxy in Pair of Galaxies
Morphological type: Sb

More info in Simbad'})]); var overlay = A.graphicOverlay({color: '#aa2222', lineWidth: 4}); + overlay.addFootprints(A.polygon([[204.970214, 0.81206], [204.97110047, 0.80993368], [204.978723, 0.79165], [204.999152, 0.800162], [204.99482125, 0.81055582], [205.002941, 0.813851], [204.99986816, 0.82141125], [205.010312, 0.825578], [205.002112, 0.846123], [204.981546, 0.837916], [204.98157771, 0.83783654], [204.962977, 0.830202], [204.9703941, 0.81213504]])); aladin.addOverlay(overlay); - overlay.addFootprints(A.polygon([[204.970214, 0.81206], [204.97110047, 0.80993368], [204.978723, 0.79165], [204.999152, 0.800162], [204.99482125, 0.81055582], [205.002941, 0.813851], [204.99986816, 0.82141125], [205.010312, 0.825578], [205.002112, 0.846123], [204.981546, 0.837916], [204.98157771, 0.83783654], [204.962977, 0.830202], [204.9703941, 0.81213504]])); aladin.displayJPG('http://images.ipac.caltech.edu/esahubble/heic0810at/esahubble_heic0810at_1600.jpg'); }); diff --git a/examples/al-init-custom-options.html b/examples/al-init-custom-options.html index 0f2b52cec..6d2f3f4f3 100644 --- a/examples/al-init-custom-options.html +++ b/examples/al-init-custom-options.html @@ -16,7 +16,7 @@ showSimbadPointerControl: true, survey: 'P/allWISE/color', // set initial image survey projection: 'AIT', // set a projection - fov: 1.5, // initial field of view in degrees + fov: 360, // initial field of view in degrees target: 'orion', // initial target cooFrame: 'icrs', // set galactic frame reticleColor: '#ff89ff', // change reticle color diff --git a/package.json b/package.json index 37866a70b..74b6f377e 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,8 @@ "HiPS" ], "scripts": { - "wasm": "wasm-pack build ./src/core --target web --release --out-name core -- --features webgl2 -Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort ", - "wasm:dbg": "wasm-pack build --dev ./src/core --target web --out-name core -- --features=webgl2,dbg -Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort ", + "wasm": "wasm-pack build ./src/core --target web --release --out-name core -- --features webgl2", + "wasm:dbg": "wasm-pack build --dev ./src/core --target web --out-name core -- --features=webgl2,dbg", "predeploy": "npm run build && rm -rf aladin-lite*.tgz && npm pack", "deploy": "python3 deploy/deploy.py", "build": "npm run wasm && vite build", diff --git a/src/core/Cargo.toml b/src/core/Cargo.toml index e6bb6425c..6dec0b670 100644 --- a/src/core/Cargo.toml +++ b/src/core/Cargo.toml @@ -22,7 +22,7 @@ url-lite = "0.1.0" serde_json = "1.0.104" serde-wasm-bindgen = "0.5" enum_dispatch = "0.3.8" -wasm-bindgen = "0.2.79" +wasm-bindgen = "0.2.92" wasm-streams = "0.3.0" async-channel = "1.8.0" mapproj = "0.3.0" @@ -55,8 +55,8 @@ branch = "master" [dependencies.moclib] package = "moc" -git = "https://github.com/bmatthieu3/cds-moc-rust" -branch = "overlap" +git = "https://github.com/cds-astro/cds-moc-rust" +branch = "main" [dependencies.serde] version = "^1.0.183" @@ -82,7 +82,7 @@ features = [ "jpeg", "png",] debug = true [profile.release] -opt-level = "z" +opt-level = 'z' debug = false debug-assertions = false overflow-checks = false diff --git a/src/core/al-api/Cargo.toml b/src/core/al-api/Cargo.toml index 8d42ca853..9719c31b6 100644 --- a/src/core/al-api/Cargo.toml +++ b/src/core/al-api/Cargo.toml @@ -9,7 +9,7 @@ js-sys = "0.3.47" cgmath = "*" serde = { version = "^1.0.59", features = ["derive"] } serde-wasm-bindgen = "0.4" -wasm-bindgen = "0.2.79" +wasm-bindgen = "0.2.92" colorgrad = "0.6.2" [features] @@ -76,16 +76,5 @@ incremental = true codegen-units = 256 rpath = false -[profile.release] -opt-level = 'z' -debug = false -debug-assertions = false -overflow-checks = false -lto = true -panic = 'unwind' -incremental = false -codegen-units = 16 -rpath = false - [package.metadata.wasm-pack.profile.release] wasm-opt = true \ No newline at end of file diff --git a/src/core/al-core/Cargo.toml b/src/core/al-core/Cargo.toml index 03b93f628..50c6b9042 100644 --- a/src/core/al-core/Cargo.toml +++ b/src/core/al-core/Cargo.toml @@ -19,7 +19,7 @@ futures = "0.3.25" colorgrad = "0.6.2" [dependencies.wasm-bindgen] -version = "0.2.79" +version = "0.2.92" [dev-dependencies] fontdue = "0.7.2" @@ -88,16 +88,5 @@ incremental = true codegen-units = 256 rpath = false -[profile.release] -opt-level = 'z' -debug = false -debug-assertions = false -overflow-checks = false -lto = true -panic = 'unwind' -incremental = false -codegen-units = 16 -rpath = false - [package.metadata.wasm-pack.profile.release] wasm-opt = true diff --git a/src/core/al-core/src/image/bitmap.rs b/src/core/al-core/src/image/bitmap.rs index 7d6c51d71..937771ea3 100644 --- a/src/core/al-core/src/image/bitmap.rs +++ b/src/core/al-core/src/image/bitmap.rs @@ -19,16 +19,23 @@ where } } } -use wasm_bindgen::JsValue; use crate::texture::Texture2DArray; +use wasm_bindgen::JsValue; impl Image for Bitmap where F: ImageFormat + Clone, { - fn tex_sub_image_3d(&self, textures: &Texture2DArray, offset: &Vector3) -> Result<(), JsValue> { - textures[offset.z as usize] - .bind() - .tex_sub_image_2d_with_u32_and_u32_and_image_bitmap(offset.x, offset.y, &self.image); + fn tex_sub_image_3d( + &self, + textures: &Texture2DArray, + offset: &Vector3, + ) -> Result<(), JsValue> { + textures.bind().tex_sub_image_3d_with_image_bitmap( + offset.z, + offset.x, + offset.y, + &self.image, + ); Ok(()) } diff --git a/src/core/al-core/src/image/canvas.rs b/src/core/al-core/src/image/canvas.rs index 3a4d79faf..2bb3af727 100644 --- a/src/core/al-core/src/image/canvas.rs +++ b/src/core/al-core/src/image/canvas.rs @@ -17,11 +17,11 @@ where } } -use cgmath::Vector3; -use wasm_bindgen::JsValue; use crate::image::format::ImageFormat; use crate::image::Image; use crate::texture::Texture2DArray; +use cgmath::Vector3; +use wasm_bindgen::JsValue; impl Image for Canvas where F: ImageFormat, @@ -33,13 +33,12 @@ where // An offset to write the image in the texture array offset: &Vector3, ) -> Result<(), JsValue> { - textures[offset.z as usize] - .bind() - .tex_sub_image_2d_with_u32_and_u32_and_html_canvas_element( - offset.x, - offset.y, - &self.canvas, - ); + textures.bind().tex_sub_image_3d_with_html_canvas_element( + offset.z, + offset.x, + offset.y, + &self.canvas, + ); Ok(()) } diff --git a/src/core/al-core/src/image/fits.rs b/src/core/al-core/src/image/fits.rs index dddc28008..ab86ca1a4 100644 --- a/src/core/al-core/src/image/fits.rs +++ b/src/core/al-core/src/image/fits.rs @@ -129,51 +129,47 @@ impl Image for Fits<'_> { match &self.data { Data::U8(data) => { let view = unsafe { R8UI::view(&data) }; - textures[offset.z as usize] - .bind() - .tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view( - offset.x, - offset.y, - self.size.x, - self.size.y, - Some(view.as_ref()), - ); + textures.bind().tex_sub_image_3d_with_opt_array_buffer_view( + offset.z, + offset.x, + offset.y, + self.size.x, + self.size.y, + Some(view.as_ref()), + ); } Data::I16(data) => { let view = unsafe { R16I::view(&data) }; - textures[offset.z as usize] - .bind() - .tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view( - offset.x, - offset.y, - self.size.x, - self.size.y, - Some(view.as_ref()), - ); + textures.bind().tex_sub_image_3d_with_opt_array_buffer_view( + offset.z, + offset.x, + offset.y, + self.size.x, + self.size.y, + Some(view.as_ref()), + ); } Data::I32(data) => { let view = unsafe { R32I::view(&data) }; - textures[offset.z as usize] - .bind() - .tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view( - offset.x, - offset.y, - self.size.x, - self.size.y, - Some(view.as_ref()), - ); + textures.bind().tex_sub_image_3d_with_opt_array_buffer_view( + offset.z, + offset.x, + offset.y, + self.size.x, + self.size.y, + Some(view.as_ref()), + ); } Data::F32(data) => { let view = unsafe { R32F::view(&data) }; - textures[offset.z as usize] - .bind() - .tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view( - offset.x, - offset.y, - self.size.x, - self.size.y, - Some(view.as_ref()), - ); + textures.bind().tex_sub_image_3d_with_opt_array_buffer_view( + offset.z, + offset.x, + offset.y, + self.size.x, + self.size.y, + Some(view.as_ref()), + ); } } diff --git a/src/core/al-core/src/image/format.rs b/src/core/al-core/src/image/format.rs index 569580af0..43cbb37bb 100644 --- a/src/core/al-core/src/image/format.rs +++ b/src/core/al-core/src/image/format.rs @@ -41,7 +41,7 @@ impl ImageFormat for RGB8U { const NUM_CHANNELS: usize = 3; const FORMAT: u32 = WebGlRenderingCtx::RGB as u32; - const INTERNAL_FORMAT: i32 = WebGlRenderingCtx::RGB as i32; + const INTERNAL_FORMAT: i32 = WebGlRenderingCtx::RGB8 as i32; const TYPE: u32 = WebGlRenderingCtx::UNSIGNED_BYTE; const CHANNEL_TYPE: ChannelType = ChannelType::RGB8U; @@ -71,7 +71,7 @@ impl ImageFormat for RGBA8U { const NUM_CHANNELS: usize = 4; const FORMAT: u32 = WebGlRenderingCtx::RGBA as u32; - const INTERNAL_FORMAT: i32 = WebGlRenderingCtx::RGBA as i32; + const INTERNAL_FORMAT: i32 = WebGlRenderingCtx::RGBA8 as i32; const TYPE: u32 = WebGlRenderingCtx::UNSIGNED_BYTE; const CHANNEL_TYPE: ChannelType = ChannelType::RGBA8U; diff --git a/src/core/al-core/src/image/html.rs b/src/core/al-core/src/image/html.rs index cbb321aef..b49d27382 100644 --- a/src/core/al-core/src/image/html.rs +++ b/src/core/al-core/src/image/html.rs @@ -17,11 +17,11 @@ where } } -use cgmath::Vector3; -use wasm_bindgen::JsValue; use crate::image::format::ImageFormat; use crate::image::Image; use crate::texture::Texture2DArray; +use cgmath::Vector3; +use wasm_bindgen::JsValue; impl Image for HTMLImage where F: ImageFormat, @@ -33,13 +33,12 @@ where // An offset to write the image in the texture array offset: &Vector3, ) -> Result<(), JsValue> { - textures[offset.z as usize] - .bind() - .tex_sub_image_2d_with_u32_and_u32_and_html_image_element( - offset.x, - offset.y, - &self.image, - ); + textures.bind().tex_sub_image_3d_with_html_image_element( + offset.z, + offset.x, + offset.y, + &self.image, + ); Ok(()) } diff --git a/src/core/al-core/src/image/mod.rs b/src/core/al-core/src/image/mod.rs index d699149e8..a242a5e42 100644 --- a/src/core/al-core/src/image/mod.rs +++ b/src/core/al-core/src/image/mod.rs @@ -229,9 +229,7 @@ where Ok(()) } } -use crate::Abort; -use std::sync::{Arc, Mutex}; /*impl Image for Arc>> where I: Image, diff --git a/src/core/al-core/src/image/raw.rs b/src/core/al-core/src/image/raw.rs index b2ea564dc..1d9ccb53d 100644 --- a/src/core/al-core/src/image/raw.rs +++ b/src/core/al-core/src/image/raw.rs @@ -31,10 +31,14 @@ where Self { data, size } } - pub fn from_encoded_raw_bytes(raw_bytes: &[u8], width: i32, height: i32) -> Result { + pub fn from_encoded_raw_bytes( + raw_bytes: &[u8], + width: i32, + height: i32, + ) -> Result { let mut decoded_bytes = match T::decode(raw_bytes).map_err(|e| JsValue::from_str(e))? { Bytes::Borrowed(bytes) => bytes.to_vec(), - Bytes::Owned(bytes) => bytes + Bytes::Owned(bytes) => bytes, }; let decoded_pixels = unsafe { @@ -80,12 +84,7 @@ where ImageBuffer::::new(data, width, height) } - pub fn tex_sub( - &mut self, - src: &Self, - s: &ImageBufferView, - d: &ImageBufferView, - ) { + pub fn tex_sub(&mut self, src: &Self, s: &ImageBufferView, d: &ImageBufferView) { let mut di = d.x; let mut dj = d.y; @@ -153,15 +152,14 @@ where ) -> Result<(), JsValue> { let js_array = <<::P as Pixel>::Container as ArrayBuffer>::new(&self.data); - textures[offset.z as usize] - .bind() - .tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view( - offset.x, - offset.y, - self.size.x, - self.size.y, - Some(js_array.as_ref()), - ); + textures.bind().tex_sub_image_3d_with_opt_array_buffer_view( + offset.z, + offset.x, + offset.y, + self.width(), + self.height(), + Some(js_array.as_ref()), + ); Ok(()) } diff --git a/src/core/al-core/src/object/framebuffer.rs b/src/core/al-core/src/object/framebuffer.rs index 6882793c3..f59e929af 100644 --- a/src/core/al-core/src/object/framebuffer.rs +++ b/src/core/al-core/src/object/framebuffer.rs @@ -1,14 +1,16 @@ use {wasm_bindgen::prelude::*, web_sys::WebGlFramebuffer}; use crate::webgl_ctx::WebGlRenderingCtx; +// Internal format used for the framebuffer final texture +use crate::image::format::RGBA8U; pub struct FrameBufferObject { gl: WebGlContext, fbo: WebGlFramebuffer, pub texture: Texture2D, } -use crate::webgl_ctx::WebGlContext; use crate::texture::Texture2D; +use crate::webgl_ctx::WebGlContext; impl FrameBufferObject { pub fn new(gl: &WebGlContext, width: usize, height: usize) -> Result { @@ -17,7 +19,7 @@ impl FrameBufferObject { .ok_or("failed to create framebuffer")?; gl.bind_framebuffer(WebGlRenderingCtx::FRAMEBUFFER, Some(&fbo)); - let texture = Texture2D::create_empty_with_format::( + let texture = Texture2D::create_empty_with_format::( gl, width as i32, height as i32, @@ -60,29 +62,39 @@ impl FrameBufferObject { self.texture.height() as usize, ) { - //let pixels = [0, 0, 0, 0].iter().cloned().cycle().take(4*height*width).collect::>(); - #[cfg(feature = "webgl2")] - self.texture - .bind_mut() - .tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array( - width as i32, - height as i32, - WebGlRenderingCtx::SRGB8_ALPHA8 as i32, - WebGlRenderingCtx::RGBA, - WebGlRenderingCtx::UNSIGNED_BYTE, - None, - ); - #[cfg(feature = "webgl1")] - self.texture - .bind_mut() - .tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array( - width as i32, - height as i32, - WebGlRenderingCtx::RGBA as i32, - WebGlRenderingCtx::RGBA, - WebGlRenderingCtx::UNSIGNED_BYTE, - None, - ); + drop(self.texture.clone()); + + self.gl + .bind_framebuffer(WebGlRenderingCtx::FRAMEBUFFER, Some(&self.fbo)); + self.texture = Texture2D::create_empty_with_format::( + &self.gl, + width as i32, + height as i32, + &[ + ( + WebGlRenderingCtx::TEXTURE_MIN_FILTER, + WebGlRenderingCtx::LINEAR, + ), + ( + WebGlRenderingCtx::TEXTURE_MAG_FILTER, + WebGlRenderingCtx::LINEAR, + ), + // Prevents s-coordinate wrapping (repeating) + ( + WebGlRenderingCtx::TEXTURE_WRAP_S, + WebGlRenderingCtx::CLAMP_TO_EDGE, + ), + // Prevents t-coordinate wrapping (repeating) + ( + WebGlRenderingCtx::TEXTURE_WRAP_T, + WebGlRenderingCtx::CLAMP_TO_EDGE, + ), + ], + ) + .unwrap(); + self.texture.attach_to_framebuffer(); + self.gl + .bind_framebuffer(WebGlRenderingCtx::FRAMEBUFFER, None); } } @@ -106,7 +118,6 @@ impl FrameBufferObject { self.bind(); // clear the fbo - self.gl.clear_color(0.0, 0.0, 0.0, 1.0); self.gl.clear(WebGlRenderingCtx::COLOR_BUFFER_BIT); // render all the things onto the fbo diff --git a/src/core/al-core/src/texture/3d.rs b/src/core/al-core/src/texture/3d.rs index 61f38a402..582ec1973 100644 --- a/src/core/al-core/src/texture/3d.rs +++ b/src/core/al-core/src/texture/3d.rs @@ -210,30 +210,6 @@ impl Texture3D { }) } - pub fn create_empty_unsized( - gl: &WebGlContext, - tex_params: &'static [(u32, u32)], - ) -> Result { - let texture = gl.create_texture(); - - gl.bind_texture(WebGlRenderingCtx::TEXTURE_2D, texture.as_ref()); - - for (pname, param) in tex_params.iter() { - gl.tex_parameteri(WebGlRenderingCtx::TEXTURE_2D, *pname, *param as i32); - } - - let gl = gl.clone(); - - let metadata = None; - Ok(Texture3D { - texture, - - gl, - - metadata, - }) - } - pub fn create_empty_with_format( gl: &WebGlContext, width: i32, diff --git a/src/core/al-core/src/texture/mod.rs b/src/core/al-core/src/texture/mod.rs index 29893ecc3..0903ee46d 100644 --- a/src/core/al-core/src/texture/mod.rs +++ b/src/core/al-core/src/texture/mod.rs @@ -4,7 +4,9 @@ pub use texture_array::Texture2DArray; pub mod pixel; pub use pixel::*; use web_sys::HtmlCanvasElement; +use web_sys::WebGlTexture; +use crate::image::format::ChannelType; use crate::webgl_ctx::WebGlContext; use crate::webgl_ctx::WebGlRenderingCtx; use wasm_bindgen::prelude::*; @@ -38,7 +40,7 @@ pub static mut CUR_IDX_TEX_UNIT: u8 = 0; #[derive(Clone)] #[allow(dead_code)] -struct Texture2DMeta { +pub struct Texture2DMeta { pub format: u32, pub internal_format: i32, pub type_: u32, @@ -47,7 +49,6 @@ struct Texture2DMeta { pub height: u32, } -use web_sys::WebGlTexture; #[derive(Clone)] pub struct Texture2D { pub texture: Option, @@ -77,7 +78,9 @@ impl Texture2D { ) -> Result { let image = HtmlImageElement::new().unwrap_abort(); + #[cfg(feature = "webgl2")] let texture = gl.create_texture(); + let onerror = { Closure::wrap(Box::new(move || { println!("Cannot load texture located at: {:?}", name); @@ -95,6 +98,7 @@ impl Texture2D { type_: F::TYPE, })); + #[cfg(feature = "webgl2")] let onload = { let image = image.clone(); let gl = gl.clone(); @@ -108,21 +112,20 @@ impl Texture2D { gl.tex_parameteri(WebGlRenderingCtx::TEXTURE_2D, *pname, *param as i32); } - #[cfg(feature = "webgl2")] - gl.tex_image_2d_with_u32_and_u32_and_html_image_element( + gl.tex_storage_2d( WebGlRenderingCtx::TEXTURE_2D, - 0, - F::INTERNAL_FORMAT, - F::FORMAT, - F::TYPE, - &image, - ) - .expect("Texture 2D"); - #[cfg(feature = "webgl1")] - gl.tex_image_2d_with_u32_and_u32_and_image( + 1, + F::INTERNAL_FORMAT as u32, + width as i32, + height as i32, + ); + gl.tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_html_image_element( WebGlRenderingCtx::TEXTURE_2D, 0, - F::INTERNAL_FORMAT, + 0, + 0, + width as i32, + height as i32, F::FORMAT, F::TYPE, &image, @@ -132,7 +135,9 @@ impl Texture2D { metadata.borrow_mut().width = image.width(); metadata.borrow_mut().height = image.height(); - //gl.generate_mipmap(WebGl2RenderingContext::TEXTURE_2D); + if F::CHANNEL_TYPE == ChannelType::RGBA8U || F::CHANNEL_TYPE == ChannelType::RGB8U { + gl.generate_mipmap(WebGlRenderingCtx::TEXTURE_2D); + } }) as Box) }; @@ -147,6 +152,7 @@ impl Texture2D { let gl = gl.clone(); Ok(Texture2D { + #[cfg(feature = "webgl2")] texture, gl, @@ -195,19 +201,30 @@ impl Texture2D { gl.tex_parameteri(WebGlRenderingCtx::TEXTURE_2D, *pname, *param as i32); } - gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array( + gl.tex_storage_2d( WebGlRenderingCtx::TEXTURE_2D, - 0, - F::INTERNAL_FORMAT, + 1, + F::INTERNAL_FORMAT as u32, width, height, + ); + gl.tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_u8_array( + WebGlRenderingCtx::TEXTURE_2D, + 0, + 0, 0, + width, + height, F::FORMAT, F::TYPE, bytes, ) .expect("Texture 2D"); + if F::CHANNEL_TYPE == ChannelType::RGBA8U || F::CHANNEL_TYPE == ChannelType::RGB8U { + gl.generate_mipmap(WebGlRenderingCtx::TEXTURE_2D); + } + let gl = gl.clone(); let metadata = Some(Rc::new(RefCell::new(Texture2DMeta { width: width as u32, @@ -226,30 +243,6 @@ impl Texture2D { }) } - pub fn create_empty_unsized( - gl: &WebGlContext, - tex_params: &'static [(u32, u32)], - ) -> Result { - let texture = gl.create_texture(); - - gl.bind_texture(WebGlRenderingCtx::TEXTURE_2D, texture.as_ref()); - - for (pname, param) in tex_params.iter() { - gl.tex_parameteri(WebGlRenderingCtx::TEXTURE_2D, *pname, *param as i32); - } - - let gl = gl.clone(); - - let metadata = None; - Ok(Texture2D { - texture, - - gl, - - metadata, - }) - } - pub fn create_empty_with_format( gl: &WebGlContext, width: i32, @@ -264,18 +257,13 @@ impl Texture2D { gl.tex_parameteri(WebGlRenderingCtx::TEXTURE_2D, *pname, *param as i32); } - gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array( + gl.tex_storage_2d( WebGlRenderingCtx::TEXTURE_2D, - 0, - F::INTERNAL_FORMAT, + 1, + F::INTERNAL_FORMAT as u32, width, height, - 0, - F::FORMAT, - F::TYPE, - None, - ) - .expect("Texture 2D"); + ); let gl = gl.clone(); let metadata = Some(Rc::new(RefCell::new(Texture2DMeta { @@ -332,13 +320,6 @@ impl Texture2D { Texture2DBound { texture_2d: self } } - pub fn bind_mut(&mut self) -> Texture2DBoundMut { - self.gl - .bind_texture(WebGlRenderingCtx::TEXTURE_2D, self.texture.as_ref()); - - Texture2DBoundMut { texture_2d: self } - } - pub fn read_pixel(&self, x: i32, y: i32) -> Result { // Create and bind the framebuffer let reader = self.gl.create_framebuffer(); @@ -621,70 +602,3 @@ impl<'a> Texture2DBound<'a> { .expect("Sub texture 2d"); } } - -pub struct Texture2DBoundMut<'a> { - texture_2d: &'a mut Texture2D, -} - -impl<'a> Texture2DBoundMut<'a> { - #[allow(dead_code)] - pub fn tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array( - &mut self, - width: i32, // Width of the image - height: i32, // Height of the image - internal_format: i32, - src_format: u32, - src_type: u32, - pixels: Option<&[u8]>, - ) { - self.texture_2d - .gl - .tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array( - WebGlRenderingCtx::TEXTURE_2D, - 0, - internal_format as i32, - width as i32, - height as i32, - 0, - src_format, - src_type, - pixels, - ) - .expect("Sub texture 2d"); - //self.texture_2d.gl.generate_mipmap(WebGlRenderingCtx::TEXTURE_2D); - - self.texture_2d.metadata = Some(Rc::new(RefCell::new(Texture2DMeta { - format: src_format, - internal_format, - type_: src_type, - width: width as u32, - height: height as u32, - }))); - } - - pub fn tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view( - &self, - dx: i32, - dy: i32, - width: i32, // Width of the image - height: i32, // Height of the image - image: Option<&js_sys::Object>, - ) { - let metadata = self.texture_2d.metadata.as_ref().unwrap_abort().borrow(); - - self.texture_2d - .gl - .tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view( - WebGlRenderingCtx::TEXTURE_2D, - 0, - dx, - dy, - width, - height, - metadata.format, - metadata.type_, - image, - ) - .expect("Sub texture 2d"); - } -} diff --git a/src/core/al-core/src/texture/texture_array.rs b/src/core/al-core/src/texture/texture_array.rs index b6a7c293e..03e30b2b3 100644 --- a/src/core/al-core/src/texture/texture_array.rs +++ b/src/core/al-core/src/texture/texture_array.rs @@ -1,20 +1,24 @@ use crate::image::format::ImageFormat; +use web_sys::HtmlCanvasElement; +use web_sys::WebGlTexture; +use crate::texture::Texture2DMeta; use crate::webgl_ctx::WebGlContext; +use crate::webgl_ctx::WebGlRenderingCtx; +use crate::Abort; +use std::cell::RefCell; +use std::rc::Rc; +use wasm_bindgen::prelude::*; +use web_sys::HtmlImageElement; pub struct Texture2DArray { - pub textures: Vec, -} + gl: WebGlContext, -use std::ops::Index; -impl Index for Texture2DArray { - type Output = Texture2D; + texture: Option, - fn index(&self, idx: usize) -> &Self::Output { - &self.textures[idx] - } + metadata: Option>>, + pub num_slices: i32, } -use super::Texture2D; -use wasm_bindgen::prelude::*; + impl Texture2DArray { pub fn create_empty( gl: &WebGlContext, @@ -26,29 +30,223 @@ impl Texture2DArray { num_slices: i32, tex_params: &'static [(u32, u32)], ) -> Result { - let textures: Result, _> = (0..num_slices) - .map(|_| Texture2D::create_empty_with_format::(gl, width, height, tex_params)) - .collect(); + let texture = gl.create_texture(); + + gl.bind_texture(WebGlRenderingCtx::TEXTURE_2D_ARRAY, texture.as_ref()); + + for (pname, param) in tex_params.iter() { + gl.tex_parameteri(WebGlRenderingCtx::TEXTURE_2D_ARRAY, *pname, *param as i32); + } + + gl.tex_storage_3d( + WebGlRenderingCtx::TEXTURE_2D_ARRAY, + 1, + F::INTERNAL_FORMAT as u32, + width, + height, + num_slices, + ); + + let gl = gl.clone(); + let metadata = Some(Rc::new(RefCell::new(Texture2DMeta { + width: width as u32, + height: height as u32, + internal_format: F::INTERNAL_FORMAT, + format: F::FORMAT, + type_: F::TYPE, + }))); Ok(Texture2DArray { - textures: textures?, + texture, + gl: gl.clone(), + num_slices, + metadata, }) } + + pub fn generate_mipmap(&self) { + self.gl.generate_mipmap(WebGlRenderingCtx::TEXTURE_2D_ARRAY); + } + + pub fn bind(&self) -> Texture2DArrayBound { + self.gl + .bind_texture(WebGlRenderingCtx::TEXTURE_2D_ARRAY, self.texture.as_ref()); + + Texture2DArrayBound { tex: self } + } + + pub fn active_texture(&self, idx_tex_unit: u8) -> &Self { + self.gl + .active_texture(WebGlRenderingCtx::TEXTURE0 + idx_tex_unit as u32); + self + } +} + +impl Drop for Texture2DArray { + fn drop(&mut self) { + self.gl.delete_texture(self.texture.as_ref()); + } } -const TEX_UNIFORMS_NAME: &[&str] = &["tex1", "tex2", "tex3", "tex4", "tex5"]; +use super::CUR_IDX_TEX_UNIT; +use crate::shader::UniformType; +use web_sys::WebGlUniformLocation; +impl UniformType for Texture2DArray { + fn uniform(gl: &WebGlContext, location: Option<&WebGlUniformLocation>, tex: &Self) { + unsafe { + let _ = tex + // 1. Active the texture unit of the texture + .active_texture(CUR_IDX_TEX_UNIT) + // 2. Bind the texture to that texture unit + .bind(); -use crate::shader::{SendUniforms, ShaderBound}; -impl SendUniforms for Texture2DArray { - fn attach_uniforms<'a>(&self, shader: &'a ShaderBound<'a>) -> &'a ShaderBound<'a> { - let num_tex = self.textures.len(); + gl.uniform1i(location, CUR_IDX_TEX_UNIT as i32); + CUR_IDX_TEX_UNIT += 1; + }; + } +} - for (idx, tex) in self.textures.iter().enumerate() { - let loc = TEX_UNIFORMS_NAME[idx]; - shader.attach_uniform(loc, tex); - } - shader.attach_uniform("num_tex", &(num_tex as i32)); +pub struct Texture2DArrayBound<'a> { + tex: &'a Texture2DArray, +} + +impl<'a> Texture2DArrayBound<'a> { + pub fn tex_sub_image_3d_with_html_image_element( + &self, + idx: i32, + dx: i32, + dy: i32, + image: &HtmlImageElement, + ) { + let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow(); + + self.tex + .gl + .tex_sub_image_3d_with_html_image_element( + WebGlRenderingCtx::TEXTURE_2D_ARRAY, + 0, + dx, + dy, + idx, + image.width() as i32, + image.height() as i32, + 1, + metadata.format, + metadata.type_, + image, + ) + .expect("Sub texture 3d"); + } + + pub fn tex_sub_image_3d_with_html_canvas_element( + &self, + idx: i32, + dx: i32, + dy: i32, + canvas: &HtmlCanvasElement, + ) { + let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow(); + + self.tex + .gl + .tex_sub_image_3d_with_html_canvas_element( + WebGlRenderingCtx::TEXTURE_2D_ARRAY, + 0, + dx, + dy, + idx, + canvas.width() as i32, + canvas.height() as i32, + 1, + metadata.format, + metadata.type_, + canvas, + ) + .expect("Sub texture 2d"); + } + + pub fn tex_sub_image_3d_with_image_bitmap( + &self, + idx: i32, + dx: i32, + dy: i32, + image: &web_sys::ImageBitmap, + ) { + let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow(); + + self.tex + .gl + .tex_sub_image_3d_with_image_bitmap( + WebGlRenderingCtx::TEXTURE_2D_ARRAY, + 0, + dx, + dy, + idx, + image.width() as i32, + image.height() as i32, + 1, + metadata.format, + metadata.type_, + image, + ) + .expect("Sub texture 2d"); + } + + pub fn tex_sub_image_3d_with_opt_array_buffer_view( + &self, + idx: i32, + dx: i32, + dy: i32, + w: i32, + h: i32, + image: Option<&js_sys::Object>, + ) { + let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow(); + + self.tex + .gl + .tex_sub_image_3d_with_opt_array_buffer_view( + WebGlRenderingCtx::TEXTURE_2D_ARRAY, + 0, + dx, + dy, + idx, + w, + h, + 1, + metadata.format, + metadata.type_, + image, + ) + .expect("Sub texture 2d"); + } - shader + #[allow(dead_code)] + pub fn tex_sub_image_3d_with_opt_u8_array( + &self, + idx: i32, + dx: i32, + dy: i32, + w: i32, + h: i32, + pixels: Option<&[u8]>, + ) { + let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow(); + self.tex + .gl + .tex_sub_image_3d_with_opt_u8_array( + WebGlRenderingCtx::TEXTURE_2D_ARRAY, + 0, + dx, + dy, + idx, + w, + h, + 1, + metadata.format, + metadata.type_, + pixels, + ) + .expect("Sub texture 2d"); } } diff --git a/src/core/al-core/src/webgl_ctx.rs b/src/core/al-core/src/webgl_ctx.rs index 96be2f4a9..0dcdead4b 100644 --- a/src/core/al-core/src/webgl_ctx.rs +++ b/src/core/al-core/src/webgl_ctx.rs @@ -39,6 +39,7 @@ impl WebGlContext { // preserveDrawingBuffer enabled for exporting the view as a PNG let context_options = js_sys::JSON::parse("{\"antialias\":false, \"preserveDrawingBuffer\": true}")?; + //js_sys::JSON::parse("{\"antialias\":false}")?; #[cfg(feature = "webgl2")] let gl = Rc::new( diff --git a/src/core/src/app.rs b/src/core/src/app.rs index b2a5033f4..6cab744a4 100644 --- a/src/core/src/app.rs +++ b/src/core/src/app.rs @@ -1,5 +1,6 @@ use crate::renderable::ImageLayer; use crate::tile_fetcher::HiPSLocalFiles; + use crate::{ //async_task::{BuildCatalogIndex, ParseTableTask, TaskExecutor, TaskResult, TaskType}, camera::CameraViewPort, @@ -18,6 +19,7 @@ use crate::{ tile_fetcher::TileFetcherQueue, time::DeltaTime, }; +use al_core::log::console_log; use wcs::WCS; use wasm_bindgen::prelude::*; @@ -83,7 +85,6 @@ pub struct App { out_of_fov: bool, //tasks_finished: bool, catalog_loaded: bool, - start_time_frame: Time, last_time_request_for_new_tiles: Time, request_for_new_tiles: bool, @@ -131,12 +132,8 @@ impl App { //let exec = Rc::new(RefCell::new(TaskExecutor::new())); let projection = ProjectionType::Sin(mapproj::zenithal::sin::Sin); - gl.blend_func_separate( - WebGl2RenderingContext::SRC_ALPHA, - WebGl2RenderingContext::ONE, - WebGl2RenderingContext::ONE, - WebGl2RenderingContext::ONE, - ); + gl.enable(WebGl2RenderingContext::BLEND); + // TODO: https://caniuse.com/?search=scissor is not supported for safari <= 14.1 // When it will be supported nearly everywhere, we will need to uncomment this line to // enable it @@ -185,13 +182,12 @@ impl App { let tile_fetcher = TileFetcherQueue::new(); //let ui = Gui::new(aladin_div_name, &gl)?; - let start_time_frame = Time::now(); let last_time_request_for_new_tiles = Time::now(); let request_for_new_tiles = true; let moc = MOCRenderer::new(&gl)?; - gl.clear_color(0.15, 0.15, 0.15, 1.0); + gl.clear_color(0.0, 0.0, 0.0, 1.0); let (img_send, img_recv) = async_channel::unbounded::(); let (ack_img_send, ack_img_recv) = async_channel::unbounded::(); @@ -205,7 +201,6 @@ impl App { Ok(App { gl, - start_time_frame, //ui, shaders, @@ -528,12 +523,9 @@ impl App { return self.inertia.is_some(); } - pub(crate) fn update(&mut self, _dt: DeltaTime) -> Result { - self.start_time_frame = Time::now(); - - //let available_tiles = self.run_tasks(dt)?; + pub(crate) fn update(&mut self, dt: DeltaTime) -> Result { if let Some(inertia) = self.inertia.as_mut() { - inertia.apply(&mut self.camera, &self.projection); + inertia.apply(&mut self.camera, &self.projection, dt); // Always request for new tiles while moving self.request_for_new_tiles = true; @@ -543,39 +535,33 @@ impl App { let thresh_speed = inertia.get_start_ampl() * 1e-3; let cur_speed = inertia.get_cur_speed(); - // Create the javascript object to pass to the callback - /*let args: js_sys::Object = js_sys::Object::new(); - let center = self.camera.get_center().lonlat(); - js_sys::Reflect::set( - &args, - &"ra".into(), - &JsValue::from_f64(center.lon().to_degrees()), - )?; - js_sys::Reflect::set( - &args, - &"dec".into(), - &JsValue::from_f64(center.lat().to_degrees()), - )?; - js_sys::Reflect::set(&args, &"dragging".into(), &JsValue::from_bool(false))?; - js_sys::Reflect::set(&args, &"inertia".into(), &JsValue::from_bool(true))?; - - // Position has changed, we call the callback - self.callback_position_changed - .call1(&JsValue::null(), &args)?; - */ - if cur_speed < thresh_speed { self.inertia = None; } } - // The rendering is done following these different situations: - // - the camera has moved + self.draw(false)?; + + // Check for async retrieval + if let Ok(img) = self.img_recv.try_recv() { + let params = img.get_params(); + self.layers.add_image( + img, + &mut self.camera, + &self.projection, + &mut self.tile_fetcher, + )?; + self.request_redraw = true; + + // Send the ack to the js promise so that she finished + let ack_img_send = self.ack_img_send.clone(); + wasm_bindgen_futures::spawn_local(async move { + ack_img_send.send(params).await.unwrap_throw(); + }) + } + let has_camera_moved = self.camera.has_moved(); - //let has_camera_recently_moved = - // ; - let _has_camera_zoomed = self.camera.has_zoomed(); { // Newly available tiles must lead to // 1. Surveys must be aware of the new available tiles @@ -584,239 +570,221 @@ impl App { /*let is_there_new_available_tiles = self .downloader .get_resolved_tiles(/*&available_tiles, */&mut self.surveys);*/ - let rscs_received = self.downloader.borrow_mut().get_received_resources(); - - let _num_tile_handled = 0; - let _tile_copied = false; - for rsc in rscs_received { - match rsc { - Resource::Tile(tile) => { - //if !_has_camera_zoomed { - if let Some(survey) = - self.layers.get_mut_hips_from_cdid(&tile.get_hips_cdid()) - { - let cfg = survey.get_config_mut(); - - if cfg.get_format() == tile.format { - let delta_depth = cfg.delta_depth(); - let fov_coverage = self.camera.get_cov(cfg.get_frame()); - let included_or_near_coverage = tile - .cell() - .get_texture_cell(delta_depth) - .get_tile_cells(delta_depth) - .any(|neighbor_tile_cell| { - fov_coverage.intersects_cell(&neighbor_tile_cell) - }); - - //let is_tile_root = tile.cell().depth() == delta_depth; - //let _depth = tile.cell().depth(); - // do not perform tex_sub costly GPU calls while the camera is zooming - if tile.cell().is_root() || included_or_near_coverage { - //let is_missing = tile.missing(); - /*self.tile_fetcher.notify_tile( - &tile, - true, - false, - &mut self.downloader, - );*/ - let Tile { - cell, - image, - time_req, - .. - } = tile; - - /*let image = if is_missing { - // Otherwise we push nothing, it is probably the case where: - // - an request error occured on a valid tile - // - the tile is not present, e.g. chandra HiPS have not the 0, 1 and 2 order tiles - None - } else { - Some(image) - };*/ - use al_core::image::ImageType; - use fitsrs::fits::Fits; - use std::io::Cursor; - //if let Some(image) = image.as_ref() { - match &*image.lock().unwrap_abort() { - Some(ImageType::FitsImage { - raw_bytes: raw_bytes_buf, - }) => { - // check if the metadata has not been set - if !cfg.fits_metadata { - let num_bytes = raw_bytes_buf.length() as usize; - let mut raw_bytes = vec![0; num_bytes]; - raw_bytes_buf.copy_to(&mut raw_bytes[..]); - - let mut bytes_reader = - Cursor::new(raw_bytes.as_slice()); - let Fits { hdu } = - Fits::from_reader(&mut bytes_reader).map_err( - |_| JsValue::from_str("Parsing fits error"), - )?; - - let header = hdu.get_header(); - let bscale = if let Some( - fitsrs::card::Value::Float(bscale), - ) = header.get(b"BSCALE ") + + if self.request_for_new_tiles + //&& Time::now() - self.last_time_request_for_new_tiles > DeltaTime::from(200.0) + { + self.look_for_new_tiles()?; + + self.request_for_new_tiles = false; + self.last_time_request_for_new_tiles = Time::now(); + } + + // Tiles are fetched if: + let fetch_tiles = self.inertia.is_none() && + // * the user is not zooming + !self.camera.has_zoomed() && + // * no inertia action is in progress + ( + // * the user is not panning the view + !self.dragging || + // * or the user is but did not move for at least 100ms + (self.dragging && Time::now() - self.camera.get_time_of_last_move() >= DeltaTime(100.0)) + ); + + if fetch_tiles { + self.tile_fetcher.notify(self.downloader.clone(), None); + } + } + + let rscs_received = self.downloader.borrow_mut().get_received_resources(); + + let mut tile_copied = false; + + for rsc in rscs_received { + match rsc { + Resource::Tile(tile) => { + //if !_has_camera_zoomed { + if let Some(survey) = self.layers.get_mut_hips_from_cdid(&tile.get_hips_cdid()) + { + let cfg = survey.get_config_mut(); + + if cfg.get_format() == tile.format { + let delta_depth = cfg.delta_depth(); + let fov_coverage = self.camera.get_cov(cfg.get_frame()); + let included_or_near_coverage = tile + .cell() + .get_texture_cell(delta_depth) + .get_tile_cells(delta_depth) + .any(|neighbor_tile_cell| { + fov_coverage.intersects_cell(&neighbor_tile_cell) + }); + + //let is_tile_root = tile.cell().depth() == delta_depth; + //let _depth = tile.cell().depth(); + // do not perform tex_sub costly GPU calls while the camera is zooming + if tile.cell().is_root() || included_or_near_coverage { + //let is_missing = tile.missing(); + /*self.tile_fetcher.notify_tile( + &tile, + true, + false, + &mut self.downloader, + );*/ + + /*let image = if is_missing { + // Otherwise we push nothing, it is probably the case where: + // - an request error occured on a valid tile + // - the tile is not present, e.g. chandra HiPS have not the 0, 1 and 2 order tiles + None + } else { + Some(image) + };*/ + use al_core::image::ImageType; + use fitsrs::fits::Fits; + use std::io::Cursor; + //if let Some(image) = image.as_ref() { + match &*tile.image.borrow() { + Some(ImageType::FitsImage { + raw_bytes: raw_bytes_buf, + }) => { + // check if the metadata has not been set + if !cfg.fits_metadata { + let num_bytes = raw_bytes_buf.length() as usize; + let mut raw_bytes = vec![0; num_bytes]; + raw_bytes_buf.copy_to(&mut raw_bytes[..]); + + let mut bytes_reader = + Cursor::new(raw_bytes.as_slice()); + let Fits { hdu } = Fits::from_reader(&mut bytes_reader) + .map_err(|_| { + JsValue::from_str("Parsing fits error") + })?; + + let header = hdu.get_header(); + let bscale = + if let Some(fitsrs::card::Value::Float(bscale)) = + header.get(b"BSCALE ") { *bscale as f32 } else { 1.0 }; - let bzero = if let Some( - fitsrs::card::Value::Float(bzero), - ) = header.get(b"BZERO ") + let bzero = + if let Some(fitsrs::card::Value::Float(bzero)) = + header.get(b"BZERO ") { *bzero as f32 } else { 0.0 }; - let blank = if let Some( - fitsrs::card::Value::Float(blank), - ) = header.get(b"BLANK ") + let blank = + if let Some(fitsrs::card::Value::Float(blank)) = + header.get(b"BLANK ") { *blank as f32 } else { std::f32::NAN }; - cfg.set_fits_metadata(bscale, bzero, blank); - } + cfg.set_fits_metadata(bscale, bzero, blank); + } + } + _ => (), + }; + //} + + let image = tile.image.clone(); + match &*image.borrow() { + Some(img) => { + if tile_copied { + self.downloader + .borrow_mut() + .delay(Resource::Tile(tile)); + continue; } - _ => (), - }; - //} - match &*image.lock().unwrap_abort() { - Some(img) => { - survey.add_tile(&cell, img, time_req)?; - self.request_redraw = true; + self.request_redraw = true; + tile_copied = true; + survey.add_tile(&tile.cell, img, tile.time_req)?; - self.time_start_blending = Time::now(); - } - None => (), - }; - } + self.time_start_blending = Time::now(); + } + None => (), + }; } } - /*} else { - self.downloader.delay_rsc(Resource::Tile(tile)); - }*/ } - Resource::Allsky(allsky) => { - let hips_cdid = allsky.get_hips_cdid(); - - if let Some(survey) = self.layers.get_mut_hips_from_cdid(hips_cdid) { - let is_missing = allsky.missing(); - if is_missing { - // The allsky image is missing so we donwload all the tiles contained into - // the 0's cell - let cfg = survey.get_config(); - for texture_cell in crate::healpix::cell::ALLSKY_HPX_CELLS_D0 { - for cell in texture_cell.get_tile_cells(cfg.delta_depth()) { - let query = query::Tile::new( - &cell, - cfg.get_creator_did().to_string(), - cfg.get_root_url().to_string(), - cfg.get_format(), - ); - self.tile_fetcher.append_base_tile(query); - } + } + Resource::Allsky(allsky) => { + let hips_cdid = allsky.get_hips_cdid(); + + if let Some(survey) = self.layers.get_mut_hips_from_cdid(hips_cdid) { + let is_missing = allsky.missing(); + if is_missing { + // The allsky image is missing so we donwload all the tiles contained into + // the 0's cell + let cfg = survey.get_config(); + for texture_cell in crate::healpix::cell::ALLSKY_HPX_CELLS_D0 { + for cell in texture_cell.get_tile_cells(cfg.delta_depth()) { + let query = query::Tile::new( + &cell, + cfg.get_creator_did().to_string(), + cfg.get_root_url().to_string(), + cfg.get_format(), + ); + self.tile_fetcher.append_base_tile(query); } - } else { - // tell the survey to not download tiles which order is <= 3 because the allsky - // give them already - survey.add_allsky(allsky)?; - // Once received ask for redraw - self.request_redraw = true; } + } else { + // tell the survey to not download tiles which order is <= 3 because the allsky + // give them already + survey.add_allsky(allsky)?; + // Once received ask for redraw + self.request_redraw = true; } } - Resource::PixelMetadata(metadata) => { - if let Some(hips) = self.layers.get_mut_hips_from_cdid(&metadata.hips_cdid) - { - let cfg = hips.get_config_mut(); - - if let Some(metadata) = *metadata.value.lock().unwrap_abort() { - cfg.blank = metadata.blank; - cfg.offset = metadata.offset; - cfg.scale = metadata.scale; - } + } + Resource::PixelMetadata(metadata) => { + if let Some(hips) = self.layers.get_mut_hips_from_cdid(&metadata.hips_cdid) { + let cfg = hips.get_config_mut(); + + if let Some(metadata) = &*metadata.value.borrow() { + cfg.blank = metadata.blank; + cfg.offset = metadata.offset; + cfg.scale = metadata.scale; } } - Resource::Moc(moc) => { - let moc_hips_cdid = moc.get_hips_cdid(); - //let url = &moc_url[..moc_url.find("/Moc.fits").unwrap_abort()]; - if let Some(hips) = self.layers.get_mut_hips_from_cdid(moc_hips_cdid) { - let request::moc::Moc { moc, .. } = moc; - - if let Some(moc) = &*moc.lock().unwrap_abort() { - hips.set_moc(moc.clone()); - - self.request_for_new_tiles = true; - self.request_redraw = true; - }; - } + } + Resource::Moc(moc) => { + let moc_hips_cdid = moc.get_hips_cdid(); + //let url = &moc_url[..moc_url.find("/Moc.fits").unwrap_abort()]; + if let Some(hips) = self.layers.get_mut_hips_from_cdid(moc_hips_cdid) { + let request::moc::Moc { moc, .. } = moc; + + if let Some(moc) = &*moc.borrow() { + hips.set_moc(moc.clone()); + + self.request_for_new_tiles = true; + self.request_redraw = true; + }; } } } - - // Tiles are fetched if: - let fetch_tiles = self.inertia.is_none() && - // * the user is not zooming - !self.camera.has_zoomed() && - // * no inertia action is in progress - ( - // * the user is not panning the view - !self.dragging || - // * or the user is but did not move for at least 100ms - (self.dragging && Time::now() - self.camera.get_time_of_last_move() >= DeltaTime(100.0)) - ); - - if fetch_tiles { - self.tile_fetcher.notify(self.downloader.clone(), None); - } - } - - // The update from the camera - //self.layers.update(&mut self.camera, &self.projection); - - if self.request_for_new_tiles - //&& Time::now() - self.last_time_request_for_new_tiles > DeltaTime::from(200.0) - { - self.look_for_new_tiles()?; - - self.request_for_new_tiles = false; - self.last_time_request_for_new_tiles = Time::now(); } // - there is at least one tile in its blending phase let blending_anim_occuring = (Time::now() - self.time_start_blending) < BLENDING_ANIM_DURATION; - // Check for async retrieval - if let Ok(img) = self.img_recv.try_recv() { - let params = img.get_params(); - self.layers.add_image( - img, - &mut self.camera, - &self.projection, - &mut self.tile_fetcher, - )?; - self.request_redraw = true; - - // Send the ack to the js promise so that she finished - let ack_img_send = self.ack_img_send.clone(); - wasm_bindgen_futures::spawn_local(async move { - ack_img_send.send(params).await.unwrap_throw(); - }) - } - - self.rendering = blending_anim_occuring | has_camera_moved | self.request_redraw /*| start_fading*/; - self.request_redraw = false; + self.rendering = blending_anim_occuring + | has_camera_moved + | self.camera.has_zoomed() + | self.request_redraw + | self.inertia.is_some(); - self.draw(false)?; + // Reset the flags about the user action + self.camera.reset(); Ok(has_camera_moved) } @@ -898,57 +866,64 @@ impl App { self.layers.reset_frame();*/ - let scene_redraw = self.rendering | force_render; + //let scene_redraw = self.rendering | force_render; + let scene_redraw = true; //let mut ui = self.ui.lock(); //let ui_redraw = ui.redraw_needed(); //if scene_redraw || ui_redraw { if scene_redraw { - //let catalogs = &self.manager; + self.request_redraw = false; + + let shaders = &mut self.shaders; + + let gl = self.gl.clone(); + + let camera = &mut self.camera; + + let grid = &mut self.grid; + let moc = &mut self.moc; + let projection = &self.projection; + + let layers = &mut self.layers; + let catalogs = &self.manager; + let colormaps = &self.colormaps; + let fbo_view = &self._fbo_view; + let final_rendering_pass = &self._final_rendering_pass; + + //fbo_view.draw_onto( + // move || { // Render the scene // Clear all the screen first (only the region set by the scissor) - self.gl - .clear(web_sys::WebGl2RenderingContext::COLOR_BUFFER_BIT); - - self.layers.draw( - &mut self.camera, - &mut self.shaders, - &self.colormaps, - &self.projection, - )?; + gl.clear(WebGl2RenderingContext::COLOR_BUFFER_BIT); + // set the blending options + layers.draw(camera, shaders, colormaps, projection)?; // Draw the catalog //let fbo_view = &self.fbo_view; //catalogs.draw(&gl, shaders, camera, colormaps, fbo_view)?; //catalogs.draw(&gl, shaders, camera, colormaps, None, self.projection)?; - self.moc.draw( - &mut self.camera, - &self.projection, - &mut self.shaders, - //&mut self.line_renderer, - )?; - - //self.line_renderer.begin(); - //Time::measure_perf("moc draw", || { - - // Ok(()) - //})?; - - self.grid - .draw(&self.camera, &self.projection, &mut self.shaders)?; - //self.line_renderer.end(); - //self.line_renderer - // .draw(&mut self.shaders, &self.camera, &self.projection)?; + gl.blend_func_separate( + WebGl2RenderingContext::SRC_ALPHA, + WebGl2RenderingContext::ONE, + WebGl2RenderingContext::ONE, + WebGl2RenderingContext::ONE, + ); + moc.draw(camera, projection, shaders)?; - //let dpi = self.camera.get_dpi(); - //ui.draw(&gl, dpi)?; + gl.blend_func_separate( + WebGl2RenderingContext::SRC_ALPHA, + WebGl2RenderingContext::ONE, + WebGl2RenderingContext::ONE, + WebGl2RenderingContext::ONE, + ); + grid.draw(camera, projection, shaders)?; - // Reset the flags about the user action - self.camera.reset(); + // Ok(()) + // }, + // None, + //)?; - /*if self.rendering { - self.layers.reset_frame(); - self.moc.reset_frame(); - }*/ + //final_rendering_pass.draw_on_screen(fbo_view, &mut self.shaders)?; } Ok(()) @@ -1374,7 +1349,9 @@ impl App { self.camera .set_aperture(self.camera.get_aperture(), &self.projection); // resize the view fbo - //self.fbo_view.resize(w as usize, h as usize); + let screen_size = self.camera.get_screen_size(); + self._fbo_view + .resize(screen_size.x as usize, screen_size.y as usize); // resize the ui fbo //self.fbo_ui.resize(w as usize, h as usize); diff --git a/src/core/src/camera/viewport.rs b/src/core/src/camera/viewport.rs index 5d5feae48..92cb9f781 100644 --- a/src/core/src/camera/viewport.rs +++ b/src/core/src/camera/viewport.rs @@ -83,7 +83,7 @@ use crate::LonLatT; use cgmath::{SquareMatrix, Vector4}; use wasm_bindgen::JsCast; -const MAX_DPI_LIMIT: f32 = 3.0; +const MAX_DPI_LIMIT: f32 = 2.0; use crate::math; use crate::time::Time; use crate::Abort; diff --git a/src/core/src/downloader/mod.rs b/src/core/src/downloader/mod.rs index 1bd8730fe..ec36e49f7 100644 --- a/src/core/src/downloader/mod.rs +++ b/src/core/src/downloader/mod.rs @@ -11,7 +11,6 @@ pub struct Downloader { queried_list: HashSet, cache: Cache, - queried_cached_ids: Vec, } use crate::fifo_cache::Cache; @@ -24,12 +23,10 @@ impl Downloader { let requests = Vec::with_capacity(32); let queried_list = HashSet::with_capacity(64); let cache = Cache::new(); - let queried_cached_ids = Vec::with_capacity(64); Self { requests, queried_list, cache, - queried_cached_ids, } } // Returns true if the fetch has been done @@ -84,10 +81,8 @@ impl Downloader { self.queried_list.remove(&query_id); } - while let Some(id) = self.queried_cached_ids.pop() { - if let Some(rsc) = self.cache.extract(&id) { - rscs.push(rsc); - } + while let Some(r) = self.cache.extract_new() { + rscs.push(r); } rscs @@ -97,8 +92,18 @@ impl Downloader { self.queried_list.contains(id) } - pub fn _delay_rsc(&mut self, rsc: Resource) { - self.queried_cached_ids.push(rsc.id().clone()); - self.cache.insert(rsc.id().clone(), rsc); + pub fn delay(&mut self, r: Resource) { + match r { + Resource::Tile(tile) => { + let k = format!( + "{:?}{:?}/{:?}", + tile.get_hips_cdid(), + tile.cell.depth(), + tile.cell.idx() + ); + self.cache.insert(k, Resource::Tile(tile)); + } + _ => unimplemented!(), + } } } diff --git a/src/core/src/downloader/request/allsky.rs b/src/core/src/downloader/request/allsky.rs index e4b238b66..ec8534f01 100644 --- a/src/core/src/downloader/request/allsky.rs +++ b/src/core/src/downloader/request/allsky.rs @@ -304,9 +304,11 @@ fn handle_allsky_fits( use al_core::image::format::RGBA8U; use crate::time::Time; +use std::cell::RefCell; +use std::rc::Rc; use std::sync::{Arc, Mutex}; pub struct Allsky { - pub image: Arc>>>, + pub image: Rc>>>, pub time_req: Time, pub depth_tile: u8, @@ -318,7 +320,7 @@ use crate::Abort; impl Allsky { pub fn missing(&self) -> bool { - self.image.lock().unwrap_abort().is_none() + self.image.borrow().is_none() } pub fn get_hips_cdid(&self) -> &CreatorDid { diff --git a/src/core/src/downloader/request/blank.rs b/src/core/src/downloader/request/blank.rs index 49cdf55d3..5e3cf02c0 100644 --- a/src/core/src/downloader/request/blank.rs +++ b/src/core/src/downloader/request/blank.rs @@ -132,10 +132,12 @@ impl From for PixelMetadataRequest { } } +use std::cell::RefCell; +use std::rc::Rc; use std::sync::{Arc, Mutex}; #[derive(Debug)] pub struct PixelMetadata { - pub value: Arc>>, + pub value: Rc>>, pub hips_cdid: CreatorDid, pub url: String, } diff --git a/src/core/src/downloader/request/moc.rs b/src/core/src/downloader/request/moc.rs index 2d71c4475..cffcb40a5 100644 --- a/src/core/src/downloader/request/moc.rs +++ b/src/core/src/downloader/request/moc.rs @@ -102,9 +102,11 @@ impl From for MOCRequest { } } +use std::cell::RefCell; +use std::rc::Rc; use std::sync::{Arc, Mutex}; pub struct Moc { - pub moc: Arc>>, + pub moc: Rc>>, pub params: al_api::moc::MOC, pub hips_cdid: Url, } diff --git a/src/core/src/downloader/request/mod.rs b/src/core/src/downloader/request/mod.rs index ac3c67c0c..f11eae0a7 100644 --- a/src/core/src/downloader/request/mod.rs +++ b/src/core/src/downloader/request/mod.rs @@ -8,12 +8,12 @@ pub mod tile; /* ------------------------------------- */ use crate::time::Time; -use std::cell::Cell; +use std::cell::{Cell, RefCell}; use std::rc::Rc; use std::sync::{Arc, Mutex}; pub type Url = String; pub struct Request { - data: Arc>>, + data: Rc>>, time_request: Time, // Flag telling if the tile has been copied so that // the HtmlImageElement can be reused to download another tile @@ -42,7 +42,7 @@ where let resolved = Rc::new(Cell::new(ResolvedStatus::NotResolved)); let time_request = Time::now(); - let data = Arc::new(Mutex::new(None)); + let data = Rc::new(RefCell::new(None)); { let data_cloned = data.clone(); @@ -51,7 +51,7 @@ where let fut = async move { let resp = f.await; if let Ok(resp) = resp { - *(data_cloned.lock().unwrap_abort()) = Some(resp); + data_cloned.replace(Some(resp)); resolved_cloned.set(ResolvedStatus::Found); } else { resolved_cloned.set(ResolvedStatus::Failed); @@ -127,13 +127,14 @@ pub enum Resource { Moc(Moc), } +/* impl Resource { pub fn id(&self) -> &String { match self { - Resource::Tile(tile) => tile.get_hips_cdid(), + Resource::Tile(tile) => &format!("{:?}:{:?}", tile.cell.depth(), tile.cell.idx()), Resource::Allsky(allsky) => allsky.get_hips_cdid(), Resource::PixelMetadata(PixelMetadata { hips_cdid, .. }) => hips_cdid, Resource::Moc(moc) => moc.get_hips_cdid(), } } -} +}*/ diff --git a/src/core/src/downloader/request/tile.rs b/src/core/src/downloader/request/tile.rs index 7f74431d3..101d74646 100644 --- a/src/core/src/downloader/request/tile.rs +++ b/src/core/src/downloader/request/tile.rs @@ -185,9 +185,11 @@ impl From for TileRequest { } use crate::time::Time; +use std::cell::RefCell; +use std::rc::Rc; use std::sync::{Arc, Mutex}; pub struct Tile { - pub image: Arc>>, + pub image: Rc>>, pub time_req: Time, pub cell: HEALPixCell, pub format: ImageFormatType, @@ -199,7 +201,7 @@ use crate::Abort; impl Tile { #[inline(always)] pub fn missing(&self) -> bool { - self.image.lock().unwrap_abort().is_none() + self.image.borrow().is_none() } #[inline(always)] diff --git a/src/core/src/fifo_cache.rs b/src/core/src/fifo_cache.rs index 65ac9ffb8..aa035ce4a 100644 --- a/src/core/src/fifo_cache.rs +++ b/src/core/src/fifo_cache.rs @@ -10,15 +10,12 @@ use crate::Abort; use std::hash::Hash; impl Cache where - K: Clone + std::cmp::Eq + Hash + K: Clone + std::cmp::Eq + Hash, { pub fn new() -> Self { let data = HashMap::with_capacity(SIZE_RESOURCE_CACHE); let order = VecDeque::with_capacity(SIZE_RESOURCE_CACHE); - Cache { - data, - order - } + Cache { data, order } } pub fn insert(&mut self, key: K, val: V) { @@ -31,11 +28,15 @@ where self.order.push_back(key); } - pub fn extract(&mut self, key: &K) -> Option { - self.data.remove(key) + pub fn extract_new(&mut self) -> Option { + if let Some(k) = self.order.pop_back() { + self.data.remove(&k) + } else { + None + } } pub fn contains(&self, key: &K) -> bool { self.data.contains_key(key) } -} \ No newline at end of file +} diff --git a/src/core/src/inertia.rs b/src/core/src/inertia.rs index 8639924a5..04f45738a 100644 --- a/src/core/src/inertia.rs +++ b/src/core/src/inertia.rs @@ -3,7 +3,7 @@ use cgmath::Vector3; use crate::camera::CameraViewPort; use crate::math::angle::ToAngle; use crate::math::projection::ProjectionType; -use crate::time::Time; +use crate::time::{DeltaTime, Time}; /// State for inertia pub struct Inertia { @@ -26,7 +26,7 @@ impl Inertia { } } - pub fn apply(&mut self, camera: &mut CameraViewPort, proj: &ProjectionType) { + pub fn apply(&mut self, camera: &mut CameraViewPort, proj: &ProjectionType, dt: DeltaTime) { let t = ((Time::now() - self.time_start).as_millis() / 1000.0) as f64; // Undamped angular frequency of the oscillator // From wiki: https://en.wikipedia.org/wiki/Harmonic_oscillator @@ -35,9 +35,11 @@ impl Inertia { // where: // * k is the stiffness of the ressort // * m is its mass - let w0 = 5.0; + let w0 = 4.0; // The angular distance goes from d0 to 0.0 - self.speed = self.ampl * ((-w0 * t).exp()); + //self.speed = self.ampl * ((-w0 * t).exp()); + // The angular distance goes from d0 to 0.0 + self.speed = self.ampl * (w0 * t + 1.0) * ((-w0 * t).exp()); /*let alpha = 1_f32 + (0_f32 - 1_f32) * (10_f32 * t + 1_f32) * (-10_f32 * t).exp(); let alpha = alpha * alpha; let fov = start_fov * (1_f32 - alpha) + goal_fov * alpha;*/ diff --git a/src/core/src/renderable/catalog/manager.rs b/src/core/src/renderable/catalog/manager.rs index 9c1b9038a..292f12b1e 100644 --- a/src/core/src/renderable/catalog/manager.rs +++ b/src/core/src/renderable/catalog/manager.rs @@ -258,11 +258,9 @@ impl Manager { fbo: Option<&FrameBufferObject>, projection: &ProjectionType, ) -> Result<(), JsValue> { - gl.enable(WebGl2RenderingContext::BLEND); for catalog in self.catalogs.values() { catalog.draw(gl, shaders, self, camera, colormaps, fbo, projection)?; } - gl.disable(WebGl2RenderingContext::BLEND); Ok(()) } diff --git a/src/core/src/renderable/final_pass.rs b/src/core/src/renderable/final_pass.rs index d3b2f71b2..eb9c83526 100644 --- a/src/core/src/renderable/final_pass.rs +++ b/src/core/src/renderable/final_pass.rs @@ -10,7 +10,6 @@ pub struct RenderPass { use crate::ShaderManager; impl RenderPass { pub fn new(gl: &WebGlContext) -> Result { - let positions = vec![0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0]; let indices = vec![0u8, 1, 2, 1, 3, 2]; let mut vao = VertexArrayObject::new(gl); @@ -49,14 +48,23 @@ impl RenderPass { }) } - pub fn draw_on_screen(&self, fbo: &FrameBufferObject, shaders: &mut ShaderManager) -> Result<(), JsValue> { - self.gl.enable(WebGl2RenderingContext::BLEND); - self.gl.blend_func( + pub fn draw_on_screen( + &self, + fbo: &FrameBufferObject, + shaders: &mut ShaderManager, + ) -> Result<(), JsValue> { + //self.gl.enable(WebGl2RenderingContext::BLEND); + /*self.gl.blend_func( WebGl2RenderingContext::ONE, WebGl2RenderingContext::ONE_MINUS_SRC_ALPHA, - ); // premultiplied alpha + ); // premultiplied alpha*/ - let shader = crate::shader::get_shader(&self.gl, shaders, "PostVS", "PostFS")?; + let shader = crate::shader::get_shader( + &self.gl, + shaders, + "passes_post_vertex_100es.vert", + "passes_post_fragment_100es.frag", + )?; shader .bind(&self.gl) @@ -69,7 +77,7 @@ impl RenderPass { 0, ); - self.gl.disable(WebGl2RenderingContext::BLEND); + //self.gl.disable(WebGl2RenderingContext::BLEND); Ok(()) } diff --git a/src/core/src/renderable/grid/mod.rs b/src/core/src/renderable/grid/mod.rs index 8b603bc8c..7aef44370 100644 --- a/src/core/src/renderable/grid/mod.rs +++ b/src/core/src/renderable/grid/mod.rs @@ -294,7 +294,6 @@ impl ProjetedGrid { let num_instances = buf.len() / 4; - self.gl.enable(WebGl2RenderingContext::BLEND); crate::shader::get_shader(&self.gl, shaders, "line_inst_ndc.vert", "line_base.frag")? .bind(&self.gl) .attach_uniform("u_color", &self.color) @@ -307,7 +306,6 @@ impl ProjetedGrid { 0, num_instances as i32, ); - self.gl.disable(WebGl2RenderingContext::BLEND); } Ok(()) diff --git a/src/core/src/renderable/hips/mod.rs b/src/core/src/renderable/hips/mod.rs index a79a93383..0dc65b824 100644 --- a/src/core/src/renderable/hips/mod.rs +++ b/src/core/src/renderable/hips/mod.rs @@ -228,12 +228,6 @@ pub struct HiPS { //#[cfg(feature = "webgl1")] // layout (location = 3) in float time_tile_received; time_tile_received: Vec, - //#[cfg(feature = "webgl1")] - // layout (location = 4) in float m0; - m0: Vec, - //#[cfg(feature = "webgl1")] - // layout (location = 5) in float m1; - m1: Vec, idx_vertices: Vec, @@ -258,8 +252,6 @@ impl HiPS { // layout (location = 2) in vec3 uv_start; // layout (location = 3) in vec3 uv_end; // layout (location = 4) in float time_tile_received; - // layout (location = 5) in float m0; - // layout (location = 6) in float m1; //let vertices = vec![0.0; MAX_NUM_FLOATS_TO_DRAW]; //let indices = vec![0_u16; MAX_NUM_INDICES_TO_DRAW]; @@ -268,8 +260,6 @@ impl HiPS { let uv_start = vec![]; let uv_end = vec![]; let time_tile_received = vec![]; - let m0 = vec![]; - let m1 = vec![]; let idx_vertices = vec![]; #[cfg(feature = "webgl2")] @@ -298,18 +288,6 @@ impl HiPS { WebGl2RenderingContext::DYNAMIC_DRAW, VecData::(&time_tile_received), ) - .add_array_buffer_single( - 1, - "m0", - WebGl2RenderingContext::DYNAMIC_DRAW, - VecData::(&m0), - ) - .add_array_buffer_single( - 1, - "m1", - WebGl2RenderingContext::DYNAMIC_DRAW, - VecData::(&m1), - ) // Set the element buffer .add_element_buffer( WebGl2RenderingContext::DYNAMIC_DRAW, @@ -342,18 +320,6 @@ impl HiPS { WebGl2RenderingContext::DYNAMIC_DRAW, VecData::(&time_tile_received), ) - .add_array_buffer( - 1, - "m0", - WebGl2RenderingContext::DYNAMIC_DRAW, - VecData::(&m0), - ) - .add_array_buffer( - 1, - "m1", - WebGl2RenderingContext::DYNAMIC_DRAW, - VecData::(&m1), - ) // Set the element buffer .add_element_buffer( WebGl2RenderingContext::DYNAMIC_DRAW, @@ -381,8 +347,6 @@ impl HiPS { uv_start, uv_end, time_tile_received, - m0, - m1, idx_vertices, @@ -553,7 +517,8 @@ impl HiPS { let slice_idx = pos_tex.z as usize; let texture_array = self.textures.get_texture_array(); - let value = texture_array[slice_idx].read_pixel(pos_tex.x, pos_tex.y)?; + unimplemented!(); + /*let value = texture_array[slice_idx].read_pixel(pos_tex.x, pos_tex.y)?; if cfg.tex_storing_fits { let value = value @@ -565,7 +530,7 @@ impl HiPS { Ok(JsValue::from_f64(value * scale + offset)) } else { Ok(value) - } + }*/ } pub fn recompute_vertices(&mut self, camera: &mut CameraViewPort, projection: &ProjectionType) { @@ -573,8 +538,6 @@ impl HiPS { self.uv_start.clear(); self.uv_end.clear(); self.time_tile_received.clear(); - self.m0.clear(); - self.m1.clear(); self.idx_vertices.clear(); let cfg = self.textures.config(); @@ -679,9 +642,6 @@ impl HiPS { let uv_1 = TileUVW::new(cell, ending_texture, cfg); let start_time = ending_texture.start_time().as_millis(); - let miss_0 = (false) as i32 as f32; - let miss_1 = (false) as i32 as f32; - let num_subdivision = num_subdivision(cell, camera, projection); let n_segments_by_side: usize = 1 << (num_subdivision as usize); @@ -729,8 +689,6 @@ impl HiPS { self.uv_start.extend(uv_start); self.uv_end.extend(uv_end); - self.m0.push(miss_0); - self.m1.push(miss_1); self.time_tile_received.push(start_time); pos.push([lon as f32, lat as f32]); @@ -787,16 +745,6 @@ impl HiPS { WebGl2RenderingContext::DYNAMIC_DRAW, VecData(&self.time_tile_received), ) - .update_array( - "m0", - WebGl2RenderingContext::DYNAMIC_DRAW, - VecData(&self.m0), - ) - .update_array( - "m1", - WebGl2RenderingContext::DYNAMIC_DRAW, - VecData(&self.m1), - ) .update_element_array( WebGl2RenderingContext::DYNAMIC_DRAW, VecData(&self.idx_vertices), @@ -861,7 +809,7 @@ impl HiPS { let raytracing = camera.is_raytracing(proj); let config = self.get_config(); - self.gl.enable(WebGl2RenderingContext::BLEND); + //self.gl.enable(WebGl2RenderingContext::BLEND); let ImageMetadata { color, @@ -935,7 +883,7 @@ impl HiPS { Ok(()) })?; - self.gl.disable(WebGl2RenderingContext::BLEND); + //self.gl.disable(WebGl2RenderingContext::BLEND); Ok(()) } diff --git a/src/core/src/renderable/hips/triangulation.rs b/src/core/src/renderable/hips/triangulation.rs index 3c917ec87..0beffb027 100644 --- a/src/core/src/renderable/hips/triangulation.rs +++ b/src/core/src/renderable/hips/triangulation.rs @@ -6,16 +6,12 @@ pub struct Triangulation { pub idx: Vec, } -use crate::math::projection::domain::sdf::{ - ProjDefType, - ProjDef, - self -}; +use crate::math::projection::domain::sdf::{self, ProjDef, ProjDefType}; impl Triangulation { pub(super) fn build(proj_def: &ProjDefType) -> Triangulation { let (mut vertices, mut idx) = (Vec::new(), Vec::new()); - // get the validity domain + // get the validity domain let root = Face::new(Vector2::new(-1_f64, -1_f64), Vector2::new(1_f64, 1_f64)); let children = root.split(2); @@ -110,7 +106,7 @@ impl Face { off_idx, off_idx + 2, off_idx + 3, - ] + ] } };*/ let idx = [ @@ -183,7 +179,7 @@ fn recursive_triangulation( vertices: &mut Vec>, idx: &mut Vec, depth: u8, - proj_def: &ProjDefType + proj_def: &ProjDefType, ) { //let (farthest_vertex, dir_farthest_vertex) = face.get_farthest_vertex(); @@ -210,7 +206,7 @@ fn recursive_triangulation( vertices, idx, depth - 1, - proj_def + proj_def, ); // top-right recursive_triangulation( @@ -218,7 +214,7 @@ fn recursive_triangulation( vertices, idx, depth - 1, - proj_def + proj_def, ); // bottom-left recursive_triangulation( @@ -226,7 +222,7 @@ fn recursive_triangulation( vertices, idx, depth - 1, - proj_def + proj_def, ); // bottom-right recursive_triangulation( @@ -234,7 +230,7 @@ fn recursive_triangulation( vertices, idx, depth - 1, - proj_def + proj_def, ); } } else { @@ -258,131 +254,163 @@ fn recursive_triangulation( match (bl_in, br_in, tr_in, tl_in) { // 0 VERTEX case - (false, false, false, false) => {}, + (false, false, false, false) => {} // 1 VERTEX cases // 1 triangle to plot // (x bl, br, tr, tl) (true, false, false, false) => { - let u = sdf::ray_marching(&tl, &D_TO_SOUTH, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&br, &D_TO_WEST, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&tl, &D_TO_SOUTH, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&br, &D_TO_WEST, proj_def).expect("should intersect domain"); face.add_triangle(&[bl, v, u], vertices, idx); - }, + } // (bl, x br, tr, tl) (false, true, false, false) => { - let u = sdf::ray_marching(&bl, &D_TO_EAST, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&tr, &D_TO_SOUTH, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&bl, &D_TO_EAST, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&tr, &D_TO_SOUTH, proj_def).expect("should intersect domain"); face.add_triangle(&[br, v, u], vertices, idx); - }, + } // (bl, br, x tr, tl) (false, false, true, false) => { - let v = sdf::ray_marching(&br, &D_TO_NORTH, proj_def).expect("should intersect domain"); - let u = sdf::ray_marching(&tl, &D_TO_EAST, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&br, &D_TO_NORTH, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&tl, &D_TO_EAST, proj_def).expect("should intersect domain"); face.add_triangle(&[tr, u, v], vertices, idx); - }, + } // (bl, br, tr, x tl) (false, false, false, true) => { - let u = sdf::ray_marching(&bl, &D_TO_NORTH, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&tr, &D_TO_WEST, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&bl, &D_TO_NORTH, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&tr, &D_TO_WEST, proj_def).expect("should intersect domain"); face.add_triangle(&[tl, u, v], vertices, idx); - }, + } // 2 VERTICES cases // (bl, x br, tr, x tl) (false, true, false, true) => { - let u = sdf::ray_marching(&bl, &D_TO_NORTH, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&bl, &D_TO_EAST, proj_def).expect("should intersect domain"); - let w = sdf::ray_marching(&tr, &D_TO_WEST, proj_def).expect("should intersect domain"); - let x = sdf::ray_marching(&tr, &D_TO_SOUTH, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&bl, &D_TO_NORTH, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&bl, &D_TO_EAST, proj_def).expect("should intersect domain"); + let w = + sdf::ray_marching(&tr, &D_TO_WEST, proj_def).expect("should intersect domain"); + let x = + sdf::ray_marching(&tr, &D_TO_SOUTH, proj_def).expect("should intersect domain"); face.add_triangle(&[u, w, tl], vertices, idx); face.add_triangle(&[u, v, w], vertices, idx); face.add_triangle(&[v, x, w], vertices, idx); face.add_triangle(&[v, br, x], vertices, idx); - }, + } // (x bl, br, x tr, tl) (true, false, true, false) => { - let u = sdf::ray_marching(&tl, &D_TO_SOUTH, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&tl, &D_TO_EAST, proj_def).expect("should intersect domain"); - let w = sdf::ray_marching(&br, &D_TO_WEST, proj_def).expect("should intersect domain"); - let x = sdf::ray_marching(&br, &D_TO_NORTH, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&tl, &D_TO_SOUTH, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&tl, &D_TO_EAST, proj_def).expect("should intersect domain"); + let w = + sdf::ray_marching(&br, &D_TO_WEST, proj_def).expect("should intersect domain"); + let x = + sdf::ray_marching(&br, &D_TO_NORTH, proj_def).expect("should intersect domain"); face.add_triangle(&[bl, w, u], vertices, idx); face.add_triangle(&[w, x, u], vertices, idx); face.add_triangle(&[x, v, u], vertices, idx); face.add_triangle(&[x, tr, v], vertices, idx); - }, + } // (bl, br, x tr, x tl) (false, false, true, true) => { - let u = sdf::ray_marching(&bl, &D_TO_NORTH, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&br, &D_TO_NORTH, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&bl, &D_TO_NORTH, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&br, &D_TO_NORTH, proj_def).expect("should intersect domain"); face.add_triangle(&[v, tl, u], vertices, idx); face.add_triangle(&[v, tr, tl], vertices, idx); - }, + } // (x bl, x br, tr, tl) (true, true, false, false) => { - let u = sdf::ray_marching(&tl, &D_TO_SOUTH, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&tr, &D_TO_SOUTH, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&tl, &D_TO_SOUTH, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&tr, &D_TO_SOUTH, proj_def).expect("should intersect domain"); face.add_triangle(&[u, bl, v], vertices, idx); face.add_triangle(&[v, bl, br], vertices, idx); - }, + } // (x bl, br, tr, x tl) (true, false, false, true) => { - let u = sdf::ray_marching(&tr, &D_TO_WEST, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&br, &D_TO_WEST, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&tr, &D_TO_WEST, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&br, &D_TO_WEST, proj_def).expect("should intersect domain"); face.add_triangle(&[bl, u, tl], vertices, idx); face.add_triangle(&[u, bl, v], vertices, idx); - }, + } // (bl, x br, x tr, tl) (false, true, true, false) => { - let u = sdf::ray_marching(&tl, &D_TO_EAST, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&bl, &D_TO_EAST, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&tl, &D_TO_EAST, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&bl, &D_TO_EAST, proj_def).expect("should intersect domain"); face.add_triangle(&[br, tr, u], vertices, idx); face.add_triangle(&[br, u, v], vertices, idx); - }, + } // 3 VERTICES cases // (x bl, x br, x tr, tl) (true, true, true, false) => { - let u = sdf::ray_marching(&tl, &D_TO_EAST, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&tl, &D_TO_SOUTH, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&tl, &D_TO_EAST, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&tl, &D_TO_SOUTH, proj_def).expect("should intersect domain"); face.add_triangle(&[u, v, bl], vertices, idx); face.add_triangle(&[u, bl, tr], vertices, idx); face.add_triangle(&[tr, bl, br], vertices, idx); - }, + } // (bl, x br, x tr, x tl) (false, true, true, true) => { - let u = sdf::ray_marching(&bl, &D_TO_NORTH, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&bl, &D_TO_EAST, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&bl, &D_TO_NORTH, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&bl, &D_TO_EAST, proj_def).expect("should intersect domain"); face.add_triangle(&[tl, u, tr], vertices, idx); face.add_triangle(&[tr, u, v], vertices, idx); face.add_triangle(&[v, br, tr], vertices, idx); - }, + } // (x bl, br, x tr, x tl) (true, false, true, true) => { - let u = sdf::ray_marching(&br, &D_TO_NORTH, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&br, &D_TO_WEST, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&br, &D_TO_NORTH, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&br, &D_TO_WEST, proj_def).expect("should intersect domain"); face.add_triangle(&[tl, bl, v], vertices, idx); face.add_triangle(&[u, tl, v], vertices, idx); face.add_triangle(&[tr, tl, u], vertices, idx); - }, + } // (x bl, x br, tr, x tl) (true, true, false, true) => { - let u = sdf::ray_marching(&tr, &D_TO_WEST, proj_def).expect("should intersect domain"); - let v = sdf::ray_marching(&tr, &D_TO_SOUTH, proj_def).expect("should intersect domain"); + let u = + sdf::ray_marching(&tr, &D_TO_WEST, proj_def).expect("should intersect domain"); + let v = + sdf::ray_marching(&tr, &D_TO_SOUTH, proj_def).expect("should intersect domain"); face.add_triangle(&[bl, u, tl], vertices, idx); face.add_triangle(&[bl, v, u], vertices, idx); face.add_triangle(&[bl, br, v], vertices, idx); - }, + } // full case must not happen _ => unreachable!(), } diff --git a/src/core/src/renderable/hips/uv.rs b/src/core/src/renderable/hips/uv.rs index b106ca9d8..a645718f2 100644 --- a/src/core/src/renderable/hips/uv.rs +++ b/src/core/src/renderable/hips/uv.rs @@ -19,36 +19,20 @@ use crate::{ pub struct TileUVW([Vector3; 4]); impl TileUVW { // The texture cell passed must be a child of texture - pub fn new( - cell: &HEALPixCell, - texture: &Texture, - cfg: &HiPSConfig, - ) -> TileUVW { + pub fn new(cell: &HEALPixCell, texture: &Texture, cfg: &HiPSConfig) -> TileUVW { // Index of the texture in the total set of textures let texture_idx = texture.idx(); - // Index of the slice of textures - let num_textures_by_slice = cfg.num_textures_by_slice(); - // Index of the texture in its slice - let idx_in_slice = texture_idx % num_textures_by_slice; - - // Index of the column of the texture in its slice - let num_textures_by_side_slice = cfg.num_textures_by_side_slice(); - let idx_col_in_slice = idx_in_slice / num_textures_by_side_slice; - // Index of the row of the texture in its slice - let idx_row_in_slice = idx_in_slice % num_textures_by_side_slice; // Row and column indexes of the tile in its texture let (idx_col_in_tex, idx_row_in_tex) = cell.offset_in_parent(texture.cell()); - let num_textures_by_side_slice_f32 = num_textures_by_side_slice as f32; - let nside = (1 << (cell.depth() - texture.cell().depth())) as f32; - let u = ((idx_row_in_slice as f32) + ((idx_row_in_tex as f32) / nside)) / num_textures_by_side_slice_f32; - let v = ((idx_col_in_slice as f32) + ((idx_col_in_tex as f32) / nside)) / num_textures_by_side_slice_f32; + let u = (idx_row_in_tex as f32) / nside; + let v = (idx_col_in_tex as f32) / nside; - let ds = 1_f32 / (num_textures_by_side_slice_f32 * nside); + let ds = 1_f32 / nside; - let w = (texture_idx as f32) / (num_textures_by_slice as f32); + let w = texture_idx as f32; TileUVW([ Vector3::new(u, v, w), Vector3::new(u + ds, v, w), diff --git a/src/core/src/renderable/image/mod.rs b/src/core/src/renderable/image/mod.rs index a28fbf262..07383ed16 100644 --- a/src/core/src/renderable/image/mod.rs +++ b/src/core/src/renderable/image/mod.rs @@ -648,7 +648,7 @@ impl Image { return Ok(()); } - self.gl.enable(WebGl2RenderingContext::BLEND); + //self.gl.enable(WebGl2RenderingContext::BLEND); let ImageMetadata { color, @@ -726,7 +726,7 @@ impl Image { //self.gl.enable(WebGl2RenderingContext::CULL_FACE); - self.gl.disable(WebGl2RenderingContext::BLEND); + //self.gl.disable(WebGl2RenderingContext::BLEND); Ok(()) } diff --git a/src/core/src/renderable/line/mod.rs b/src/core/src/renderable/line/mod.rs index c4896540f..e81bb658f 100644 --- a/src/core/src/renderable/line/mod.rs +++ b/src/core/src/renderable/line/mod.rs @@ -351,13 +351,13 @@ impl RasterizedLineRenderer { camera: &CameraViewPort, proj: &ProjectionType, ) -> Result<(), JsValue> { - self.gl.enable(WebGl2RenderingContext::BLEND); - self.gl.blend_func_separate( + //self.gl.enable(WebGl2RenderingContext::BLEND); + /*self.gl.blend_func_separate( WebGl2RenderingContext::SRC_ALPHA, WebGl2RenderingContext::ONE_MINUS_SRC_ALPHA, WebGl2RenderingContext::ONE, WebGl2RenderingContext::ONE, - ); + );*/ //self.gl.disable(WebGl2RenderingContext::CULL_FACE); { @@ -425,7 +425,7 @@ impl RasterizedLineRenderer { _ => (), } } - self.gl.disable(WebGl2RenderingContext::BLEND); + //self.gl.disable(WebGl2RenderingContext::BLEND); Ok(()) } diff --git a/src/core/src/renderable/moc/mod.rs b/src/core/src/renderable/moc/mod.rs index b1f713e04..e4a13470f 100644 --- a/src/core/src/renderable/moc/mod.rs +++ b/src/core/src/renderable/moc/mod.rs @@ -553,7 +553,7 @@ impl MOCIntern { let view2world = camera.get_m2w(); let icrs2world = view2world * icrs2view; - self.gl.enable(WebGl2RenderingContext::BLEND); + //self.gl.enable(WebGl2RenderingContext::BLEND); crate::shader::get_shader(&self.gl, shaders, "moc_base.vert", "moc_base.frag")? .bind(&self.gl) @@ -569,7 +569,7 @@ impl MOCIntern { 0, ); - self.gl.disable(WebGl2RenderingContext::BLEND); + //self.gl.disable(WebGl2RenderingContext::BLEND); } } Ok(()) diff --git a/src/core/src/renderable/mod.rs b/src/core/src/renderable/mod.rs index 6e58c7eab..1eecea7a6 100644 --- a/src/core/src/renderable/mod.rs +++ b/src/core/src/renderable/mod.rs @@ -76,9 +76,9 @@ pub struct Layers { } const DEFAULT_BACKGROUND_COLOR: ColorRGB = ColorRGB { - r: 0.05, - g: 0.05, - b: 0.05, + r: 0.0, + g: 0.0, + b: 0.0, }; fn get_backgroundcolor_shader<'a>( @@ -260,8 +260,6 @@ impl Layers { ); } - // The first layer must be paint independently of its alpha channel - self.gl.enable(WebGl2RenderingContext::BLEND); // Pre loop over the layers to see if a HiPS is entirely covering those behind // so that we do not have to render those let mut idx_start_layer = 0; @@ -301,14 +299,6 @@ impl Layers { } } - self.gl.blend_func_separate( - WebGl2RenderingContext::SRC_ALPHA, - WebGl2RenderingContext::ONE, - WebGl2RenderingContext::ONE, - WebGl2RenderingContext::ONE, - ); - self.gl.disable(WebGl2RenderingContext::BLEND); - Ok(()) } diff --git a/src/core/src/renderable/shape/polyline.rs b/src/core/src/renderable/shape/polyline.rs index 8573d4aba..8bbe3f55f 100644 --- a/src/core/src/renderable/shape/polyline.rs +++ b/src/core/src/renderable/shape/polyline.rs @@ -176,13 +176,13 @@ impl PolylineRenderer { camera: &CameraViewPort, proj: &ProjectionType, ) -> Result<(), JsValue> { - self.gl.enable(WebGl2RenderingContext::BLEND); - self.gl.blend_func_separate( + //self.gl.enable(WebGl2RenderingContext::BLEND); + /*self.gl.blend_func_separate( WebGl2RenderingContext::SRC_ALPHA, WebGl2RenderingContext::ONE_MINUS_SRC_ALPHA, WebGl2RenderingContext::ONE, WebGl2RenderingContext::ONE, - ); + );*/ // draw the instanced lines let icrs2view = CooSystem::ICRS.to(camera.get_coo_system()); @@ -203,7 +203,7 @@ impl PolylineRenderer { self.num_instances as i32, ); - self.gl.disable(WebGl2RenderingContext::BLEND); + //self.gl.disable(WebGl2RenderingContext::BLEND); Ok(()) } diff --git a/src/core/src/survey/buffer.rs b/src/core/src/survey/buffer.rs index e140d9450..ff718eaf3 100644 --- a/src/core/src/survey/buffer.rs +++ b/src/core/src/survey/buffer.rs @@ -7,6 +7,7 @@ use al_core::image::format::ChannelType; use cgmath::Vector3; use al_api::hips::ImageExt; +use al_core::webgl_ctx::WebGlRenderingCtx; use al_core::image::format::ImageFormat; #[cfg(feature = "webgl2")] @@ -14,7 +15,6 @@ use al_core::image::format::{R16I, R32I, R8UI}; use al_core::image::format::{R32F, R64F, RGB8U, RGBA8U}; use al_core::image::Image; use al_core::shader::{SendUniforms, ShaderBound}; -use al_core::texture::TEX_PARAMS; use al_core::Texture2DArray; use al_core::WebGlContext; @@ -129,7 +129,7 @@ pub struct ImageSurveyTextures { pub config: HiPSConfig, heap: HEALPixCellHeap, - //num_root_textures_available: usize, + num_root_textures_available: u8, size: usize, pub textures: HashMap, @@ -155,20 +155,43 @@ fn create_texture_array( config: &HiPSConfig, ) -> Result { let texture_size = config.get_texture_size(); - let num_textures_by_side_slice = config.num_textures_by_side_slice(); - let num_slices = config.num_slices(); Texture2DArray::create_empty::( gl, - texture_size * num_textures_by_side_slice, - texture_size * num_textures_by_side_slice, - num_slices, - TEX_PARAMS, + texture_size, + texture_size, + // 256 is a consensus for targetting the maximum GPU architectures. We create a 128 slices to optimize performance + 128, + &[ + ( + WebGlRenderingCtx::TEXTURE_MIN_FILTER, + // apply mipmapping + WebGlRenderingCtx::NEAREST_MIPMAP_NEAREST, + ), + ( + WebGlRenderingCtx::TEXTURE_MAG_FILTER, + WebGlRenderingCtx::NEAREST, + ), + // Prevents s-coordinate wrapping (repeating) + ( + WebGlRenderingCtx::TEXTURE_WRAP_S, + WebGlRenderingCtx::CLAMP_TO_EDGE, + ), + // Prevents t-coordinate wrapping (repeating) + ( + WebGlRenderingCtx::TEXTURE_WRAP_T, + WebGlRenderingCtx::CLAMP_TO_EDGE, + ), + ( + WebGlRenderingCtx::TEXTURE_WRAP_R, + WebGlRenderingCtx::CLAMP_TO_EDGE, + ), + ], ) } impl ImageSurveyTextures { pub fn new(gl: &WebGlContext, config: HiPSConfig) -> Result { - let size = config.num_textures() - NUM_HPX_TILES_DEPTH_ZERO; + let size = 128 - NUM_HPX_TILES_DEPTH_ZERO; // Ensures there is at least space for the 12 // root textures //debug_assert!(size >= NUM_HPX_TILES_DEPTH_ZERO); @@ -209,7 +232,7 @@ impl ImageSurveyTextures { }; // The root textures have not been loaded //let ready = false; - //let num_root_textures_available = 0; + let num_root_textures_available = 0; let available_tiles_during_frame = false; let start_time = None; //let num_base_textures = 0; @@ -218,7 +241,7 @@ impl ImageSurveyTextures { heap, size, - //num_root_textures_available, + num_root_textures_available, textures, base_textures, //num_base_textures, @@ -270,7 +293,7 @@ impl ImageSurveyTextures { self.heap.clear(); self.textures.clear(); //self.ready = false; - //self.num_root_textures_available = 0; + self.num_root_textures_available = 0; self.available_tiles_during_frame = false; self.start_time = None; @@ -286,7 +309,7 @@ impl ImageSurveyTextures { } = allsky; { - let mutex_locked = image.lock().unwrap_abort(); + let mutex_locked = image.borrow(); let images = mutex_locked.as_ref().unwrap_abort(); for (idx, image) in images.iter().enumerate() { self.push(&HEALPixCell(depth_tile, idx as u64), image, time_req)?; @@ -366,6 +389,13 @@ impl ImageSurveyTextures { self.textures.insert(tex_cell, texture); } + if tex_cell_is_root { + self.num_root_textures_available += 1; + if self.num_root_textures_available == 12 { + self.texture_2d_array.generate_mipmap() + } + } + // At this point, the texture that should contain the tile // is in the buffer // and the tile is not already in any textures of the buffer @@ -515,36 +545,26 @@ impl ImageSurveyTextures { // Index of the texture in the total set of textures let texture_idx = texture.idx(); - // Index of the slice of textures - let num_textures_by_slice = cfg.num_textures_by_slice(); - let idx_slice = texture_idx / num_textures_by_slice; - // Index of the texture in its slice - let idx_in_slice = texture_idx % num_textures_by_slice; - - // Index of the column of the texture in its slice - let num_textures_by_side_slice = cfg.num_textures_by_side_slice(); - let idx_col_in_slice = idx_in_slice / num_textures_by_side_slice; - // Index of the row of the texture in its slice - let idx_row_in_slice = idx_in_slice % num_textures_by_side_slice; // The size of the global texture containing the tiles let texture_size = cfg.get_texture_size(); // Offset in the slice in pixels let mut offset = Vector3::new( - (idx_row_in_slice as i32) * texture_size + ((dy * (texture_size as f64)) as i32), - (idx_col_in_slice as i32) * texture_size + ((dx * (texture_size as f64)) as i32), - idx_slice, + (dy * (texture_size as f64)) as i32, + (dx * (texture_size as f64)) as i32, + texture_idx, ); // Offset in the slice in pixels if self.config.tex_storing_fits { - let mut uvy = offset.y as f32 / 4096.0; + let texture_size = self.config.get_texture_size() as f32; + let mut uvy = offset.y as f32 / texture_size; uvy = self.config.size_tile_uv + 2.0 * self.config.size_tile_uv * (uvy / self.config.size_tile_uv).floor() - uvy; - offset.y = (uvy * 4096.0) as i32; + offset.y = (uvy * texture_size) as i32; } Ok(offset) @@ -636,17 +656,7 @@ fn send_to_gpu( // Index of the texture in the total set of textures let texture_idx = texture.idx(); // Index of the slice of textures - let num_textures_by_slice = cfg.num_textures_by_slice(); - let idx_slice = texture_idx / num_textures_by_slice; - // Index of the texture in its slice - let idx_in_slice = texture_idx % num_textures_by_slice; - - // Index of the column of the texture in its slice - let num_textures_by_side_slice = cfg.num_textures_by_side_slice(); - let idx_col_in_slice = idx_in_slice / num_textures_by_side_slice; - // Index of the row of the texture in its slice - let idx_row_in_slice = idx_in_slice % num_textures_by_side_slice; - + let idx_slice = texture_idx; // Row and column indexes of the tile in its texture let delta_depth = cfg.delta_depth(); let (idx_col_in_tex, idx_row_in_tex) = cell.get_offset_in_texture_cell(delta_depth); @@ -658,8 +668,8 @@ fn send_to_gpu( // Offset in the slice in pixels let offset = Vector3::new( - (idx_row_in_slice as i32) * texture_size + (idx_row_in_tex as i32) * tile_size, - (idx_col_in_slice as i32) * texture_size + (idx_col_in_tex as i32) * tile_size, + (idx_row_in_tex as i32) * tile_size, + (idx_col_in_tex as i32) * tile_size, idx_slice, ); @@ -685,17 +695,13 @@ impl SendUniforms for ImageSurveyTextures { let texture = self.get(&cell).unwrap(); let texture_uniforms = TextureUniforms::new(texture, idx as i32); shader.attach_uniforms_from(&texture_uniforms); - /*else { - let texture = &Texture::new(&cell, idx as i32, Time::now()); - let texture_uniforms = TextureUniforms::new(texture, idx as i32); - shader.attach_uniforms_from(&texture_uniforms); - }*/ } //} let shader = shader .attach_uniforms_from(&self.config) - .attach_uniforms_from(&self.texture_2d_array); + .attach_uniform("tex", &self.texture_2d_array) + .attach_uniform("num_slices", &(self.texture_2d_array.num_slices as i32)); shader } diff --git a/src/core/src/survey/config.rs b/src/core/src/survey/config.rs index 87e1cd3a7..c687956f0 100644 --- a/src/core/src/survey/config.rs +++ b/src/core/src/survey/config.rs @@ -150,7 +150,6 @@ pub struct HiPSConfig { // Max depth of the current HiPS tiles max_depth_texture: u8, max_depth_tile: u8, - num_textures: usize, pub is_allsky: bool, @@ -180,10 +179,6 @@ use crate::HiPSProperties; use al_api::coo_system::CooSystem; use wasm_bindgen::JsValue; -const NUM_TEXTURES_BY_SIDE_SLICE: i32 = 8; -const NUM_TEXTURES_BY_SLICE: i32 = NUM_TEXTURES_BY_SIDE_SLICE * NUM_TEXTURES_BY_SIDE_SLICE; -const NUM_SLICES: i32 = 1; - impl HiPSConfig { /// Define a HiPS configuration /// @@ -196,7 +191,6 @@ impl HiPSConfig { let creator_did = properties.get_creator_did().to_string(); // Define the size of the 2d texture array depending on the // characterics of the client - let num_textures = (NUM_TEXTURES_BY_SLICE * NUM_SLICES) as usize; let max_depth_tile = properties.get_max_order(); let tile_size = properties.get_tile_size(); @@ -295,7 +289,7 @@ impl HiPSConfig { let num_tiles_per_texture = num_tile_per_side_texture * num_tile_per_side_texture; let max_depth_texture = max_depth_tile - delta_depth; - let size_tile_uv = 1_f32 / ((8 << delta_depth) as f32); + let size_tile_uv = 1_f32 / ((1 << delta_depth) as f32); let frame = properties.get_frame(); let sky_fraction = properties.get_sky_fraction().unwrap_or(1.0); @@ -326,7 +320,6 @@ impl HiPSConfig { max_depth_tile, min_depth_texture, min_depth_tile, - num_textures, is_allsky, @@ -505,26 +498,6 @@ impl HiPSConfig { self.frame } - #[inline(always)] - pub fn num_textures(&self) -> usize { - self.num_textures - } - - #[inline(always)] - pub fn num_textures_by_side_slice(&self) -> i32 { - NUM_TEXTURES_BY_SIDE_SLICE - } - - #[inline(always)] - pub fn num_textures_by_slice(&self) -> i32 { - NUM_TEXTURES_BY_SLICE - } - - #[inline(always)] - pub fn num_slices(&self) -> i32 { - NUM_SLICES - } - #[inline(always)] pub fn get_format(&self) -> ImageFormatType { self.format diff --git a/src/glsl/webgl2/fits/base.vert b/src/glsl/webgl2/fits/base.vert index 419653330..1741f8615 100644 --- a/src/glsl/webgl2/fits/base.vert +++ b/src/glsl/webgl2/fits/base.vert @@ -1,5 +1,5 @@ #version 300 es -precision highp float; +precision lowp float; precision mediump int; layout (location = 0) in vec2 ndc_pos; diff --git a/src/glsl/webgl2/fits/isampler.frag b/src/glsl/webgl2/fits/isampler.frag index b5d61f8fd..4b6923ad1 100644 --- a/src/glsl/webgl2/fits/isampler.frag +++ b/src/glsl/webgl2/fits/isampler.frag @@ -1,8 +1,8 @@ #version 300 es -precision highp float; -precision highp sampler2D; -precision highp isampler2D; -precision highp usampler2D; +precision lowp float; +precision lowp sampler2D; +precision lowp isampler2D; +precision lowp usampler2D; precision mediump int; out vec4 out_frag_color; @@ -11,7 +11,30 @@ in vec2 frag_uv; uniform isampler2D tex; uniform float opacity; -#include ../hips/color.glsl; +uniform float scale; +uniform float offset; +uniform float blank; + +uniform float min_value; +uniform float max_value; +uniform int H; + +uniform float reversed; + +#include ./../colormaps/colormap.glsl; +#include ./../hips/transfer_funcs.glsl; +#include ./../hips/tonal_corrections.glsl; + +vec4 apply_colormap_to_grayscale(float x, float a) { + float alpha = x * scale + offset; + alpha = transfer_func(H, alpha, min_value, max_value); + + // apply reversed + alpha = mix(alpha, 1.0 - alpha, reversed); + + vec4 new_color = mix(colormap_f(alpha) * a, vec4(0.0), float(x == blank || isnan(x))); + return apply_tonal(new_color); +} void main() { ivec4 color = texture(tex, frag_uv); diff --git a/src/glsl/webgl2/fits/sampler.frag b/src/glsl/webgl2/fits/sampler.frag index 27acef924..cded386ad 100644 --- a/src/glsl/webgl2/fits/sampler.frag +++ b/src/glsl/webgl2/fits/sampler.frag @@ -1,8 +1,8 @@ #version 300 es -precision highp float; -precision highp sampler2D; -precision highp isampler2D; -precision highp usampler2D; +precision lowp float; +precision lowp sampler2D; +precision lowp isampler2D; +precision lowp usampler2D; precision mediump int; out vec4 out_frag_color; @@ -11,7 +11,30 @@ in vec2 frag_uv; uniform sampler2D tex; uniform float opacity; -#include ../hips/color.glsl; +uniform float scale; +uniform float offset; +uniform float blank; + +uniform float min_value; +uniform float max_value; +uniform int H; + +uniform float reversed; + +#include ./../colormaps/colormap.glsl; +#include ./../hips/transfer_funcs.glsl; +#include ./../hips/tonal_corrections.glsl; + +vec4 apply_colormap_to_grayscale(float x, float a) { + float alpha = x * scale + offset; + alpha = transfer_func(H, alpha, min_value, max_value); + + // apply reversed + alpha = mix(alpha, 1.0 - alpha, reversed); + + vec4 new_color = mix(colormap_f(alpha) * a, vec4(0.0), float(x == blank || isnan(x))); + return apply_tonal(new_color); +} void main() { vec4 color = texture(tex, frag_uv); diff --git a/src/glsl/webgl2/fits/usampler.frag b/src/glsl/webgl2/fits/usampler.frag index cc3479326..82a40e891 100644 --- a/src/glsl/webgl2/fits/usampler.frag +++ b/src/glsl/webgl2/fits/usampler.frag @@ -1,8 +1,8 @@ #version 300 es -precision highp float; -precision highp sampler2D; -precision highp isampler2D; -precision highp usampler2D; +precision lowp float; +precision lowp sampler2D; +precision lowp isampler2D; +precision lowp usampler2D; precision mediump int; out vec4 out_frag_color; @@ -11,7 +11,30 @@ in vec2 frag_uv; uniform usampler2D tex; uniform float opacity; -#include ../hips/color.glsl; +uniform float scale; +uniform float offset; +uniform float blank; + +uniform float min_value; +uniform float max_value; +uniform int H; + +uniform float reversed; + +#include ./../colormaps/colormap.glsl; +#include ./../hips/transfer_funcs.glsl; +#include ./../hips/tonal_corrections.glsl; + +vec4 apply_colormap_to_grayscale(float x, float a) { + float alpha = x * scale + offset; + alpha = transfer_func(H, alpha, min_value, max_value); + + // apply reversed + alpha = mix(alpha, 1.0 - alpha, reversed); + + vec4 new_color = mix(colormap_f(alpha) * a, vec4(0.0), float(x == blank || isnan(x))); + return apply_tonal(new_color); +} void main() { uvec4 color = texture(tex, frag_uv); diff --git a/src/glsl/webgl2/hips/color.glsl b/src/glsl/webgl2/hips/color.glsl index 65ffa322e..000f5fe8a 100644 --- a/src/glsl/webgl2/hips/color.glsl +++ b/src/glsl/webgl2/hips/color.glsl @@ -1,10 +1,3 @@ -//const int MAX_NUM_TEX = 3; -uniform sampler2D tex1; -uniform sampler2D tex2; -//uniform sampler2D tex3; - -uniform int num_tex; - uniform float scale; uniform float offset; uniform float blank; @@ -13,6 +6,8 @@ uniform float min_value; uniform float max_value; uniform int H; +uniform float reversed; + uniform float size_tile_uv; uniform int tex_storing_fits; @@ -23,16 +18,7 @@ uniform int tex_storing_fits; #include ./hsv.glsl; vec4 get_pixels(vec3 uv) { - - /*if (idx_texture == 0) { - return texture(tex1, uv.xy); - } else if (idx_texture == 1) { - return texture(tex2, uv.xy); - } else { - return vec4(0.0, 1.0, 0.0, 1.0); - }*/ - int idx_texture = int(uv.z); - return mix(texture(tex1, uv.xy), texture(tex2, uv.xy), float(idx_texture)); + return texture(tex, uv); } vec3 reverse_uv(vec3 uv) { @@ -40,7 +26,6 @@ vec3 reverse_uv(vec3 uv) { return uv; } -uniform float reversed; vec4 get_color_from_texture(vec3 UV) { vec4 color = get_pixels(UV); diff --git a/src/glsl/webgl2/hips/color_i.glsl b/src/glsl/webgl2/hips/color_i.glsl index f2447bbc9..f07a7d0a9 100644 --- a/src/glsl/webgl2/hips/color_i.glsl +++ b/src/glsl/webgl2/hips/color_i.glsl @@ -1,8 +1,3 @@ -//const int MAX_NUM_TEX = 3; -uniform isampler2D tex1; -uniform isampler2D tex2; -//uniform isampler2D tex3; -uniform int num_tex; uniform float scale; uniform float offset; @@ -22,19 +17,7 @@ uniform int tex_storing_fits; #include ./tonal_corrections.glsl; ivec4 get_pixels(vec3 uv) { - /*int idx_texture = int(uv.z); - if (idx_texture == 0) { - return texture(tex1, uv.xy); - } else if (idx_texture == 1) { - return texture(tex2, uv.xy); - } else if (idx_texture == 2) { - return texture(tex3, uv.xy); - } else { - return ivec4(0, 0, 0, 1); - }*/ - //return texture(tex1, uv.xy); - int idx_texture = int(uv.z); - return ivec4(mix(vec4(texture(tex1, uv.xy)), vec4(texture(tex2, uv.xy)), float(idx_texture))); + return ivec4(texture(tex, uv)); } vec3 reverse_uv(vec3 uv) { diff --git a/src/glsl/webgl2/hips/color_u.glsl b/src/glsl/webgl2/hips/color_u.glsl index fc2084c57..16c005fd2 100644 --- a/src/glsl/webgl2/hips/color_u.glsl +++ b/src/glsl/webgl2/hips/color_u.glsl @@ -1,9 +1,3 @@ -//const int MAX_NUM_TEX = 3; -uniform usampler2D tex1; -uniform usampler2D tex2; -//uniform usampler2D tex3; -uniform int num_tex; - uniform float scale; uniform float offset; uniform float blank; @@ -22,20 +16,7 @@ uniform int tex_storing_fits; #include ./tonal_corrections.glsl; uvec4 get_pixels(vec3 uv) { - /*int idx_texture = int(uv.z); - if (idx_texture == 0) { - return texture(tex1, uv.xy); - } else if (idx_texture == 1) { - return texture(tex2, uv.xy); - } else if (idx_texture == 2) { - return texture(tex3, uv.xy); - } else { - return uvec4(0, 0, 0, 1); - }*/ - //return texture(tex1, uv.xy); - //int idx_texture = int(uv.z); - int idx_texture = int(uv.z); - return uvec4(mix(vec4(texture(tex1, uv.xy)), vec4(texture(tex2, uv.xy)), float(idx_texture))); + return uvec4(texture(tex, uv)); } vec3 reverse_uv(vec3 uv) { diff --git a/src/glsl/webgl2/hips/rasterizer/color.frag b/src/glsl/webgl2/hips/rasterizer/color.frag index a970b1bfa..2d70dc02e 100644 --- a/src/glsl/webgl2/hips/rasterizer/color.frag +++ b/src/glsl/webgl2/hips/rasterizer/color.frag @@ -1,14 +1,14 @@ #version 300 es -precision highp float; -precision highp sampler2D; -precision highp isampler2D; -precision mediump int; +precision lowp float; +precision lowp sampler2DArray; +precision lowp isampler2DArray; +precision lowp usampler2DArray; + +uniform sampler2DArray tex; in vec3 frag_uv_start; in vec3 frag_uv_end; in float frag_blending_factor; -in float m_start; -in float m_end; out vec4 out_frag_color; uniform float opacity; diff --git a/src/glsl/webgl2/hips/rasterizer/grayscale_to_colormap.frag b/src/glsl/webgl2/hips/rasterizer/grayscale_to_colormap.frag index 26ec68888..5b7a57d2f 100644 --- a/src/glsl/webgl2/hips/rasterizer/grayscale_to_colormap.frag +++ b/src/glsl/webgl2/hips/rasterizer/grayscale_to_colormap.frag @@ -1,14 +1,14 @@ #version 300 es -precision highp float; -precision highp sampler2D; -precision highp isampler2D; -precision mediump int; +precision lowp float; +precision lowp sampler2DArray; +precision lowp isampler2DArray; +precision lowp usampler2DArray; + +uniform sampler2DArray tex; in vec3 frag_uv_start; in vec3 frag_uv_end; in float frag_blending_factor; -in float m_start; -in float m_end; out vec4 out_frag_color; diff --git a/src/glsl/webgl2/hips/rasterizer/grayscale_to_colormap_i.frag b/src/glsl/webgl2/hips/rasterizer/grayscale_to_colormap_i.frag index aa78d645d..0c2dd5d02 100644 --- a/src/glsl/webgl2/hips/rasterizer/grayscale_to_colormap_i.frag +++ b/src/glsl/webgl2/hips/rasterizer/grayscale_to_colormap_i.frag @@ -1,14 +1,14 @@ #version 300 es -precision highp float; -precision highp sampler2D; -precision highp isampler2D; -precision mediump int; +precision lowp float; +precision lowp sampler2DArray; +precision lowp isampler2DArray; +precision lowp usampler2DArray; + +uniform isampler2DArray tex; in vec3 frag_uv_start; in vec3 frag_uv_end; in float frag_blending_factor; -in float m_start; -in float m_end; out vec4 out_frag_color; diff --git a/src/glsl/webgl2/hips/rasterizer/grayscale_to_colormap_u.frag b/src/glsl/webgl2/hips/rasterizer/grayscale_to_colormap_u.frag index b6bf47510..fc4ff7ec5 100644 --- a/src/glsl/webgl2/hips/rasterizer/grayscale_to_colormap_u.frag +++ b/src/glsl/webgl2/hips/rasterizer/grayscale_to_colormap_u.frag @@ -1,15 +1,14 @@ #version 300 es -precision highp float; -precision highp sampler2D; -precision highp isampler2D; -precision highp usampler2D; -precision mediump int; +precision lowp float; +precision lowp sampler2DArray; +precision lowp isampler2DArray; +precision lowp usampler2DArray; + +uniform usampler2DArray tex; in vec3 frag_uv_start; in vec3 frag_uv_end; in float frag_blending_factor; -in float m_start; -in float m_end; out vec4 out_frag_color; diff --git a/src/glsl/webgl2/hips/rasterizer/raster.vert b/src/glsl/webgl2/hips/rasterizer/raster.vert index 7b99eaa77..fd66d787c 100644 --- a/src/glsl/webgl2/hips/rasterizer/raster.vert +++ b/src/glsl/webgl2/hips/rasterizer/raster.vert @@ -1,20 +1,15 @@ #version 300 es -precision highp float; -precision mediump int; +precision lowp float; //layout (location = 0) in vec3 position; layout (location = 0) in vec2 lonlat; layout (location = 1) in vec3 uv_start; layout (location = 2) in vec3 uv_end; layout (location = 3) in float time_tile_received; -layout (location = 4) in float m0; -layout (location = 5) in float m1; out vec3 frag_uv_start; out vec3 frag_uv_end; out float frag_blending_factor; -out float m_start; -out float m_end; // current time in ms uniform mat4 inv_model; @@ -36,6 +31,4 @@ void main() { frag_uv_start = uv_start; frag_uv_end = uv_end; frag_blending_factor = min((current_time - time_tile_received) / 200.0, 1.0); - m_start = m0; - m_end = m1; } \ No newline at end of file diff --git a/src/glsl/webgl2/hips/raytracer/backcolor.frag b/src/glsl/webgl2/hips/raytracer/backcolor.frag index 371770c06..1ca4d3cc4 100644 --- a/src/glsl/webgl2/hips/raytracer/backcolor.frag +++ b/src/glsl/webgl2/hips/raytracer/backcolor.frag @@ -1,8 +1,5 @@ #version 300 es -precision highp float; -precision highp sampler2D; -precision highp usampler2D; -precision highp isampler2D; +precision lowp float; precision mediump int; out vec4 out_frag_color; diff --git a/src/glsl/webgl2/hips/raytracer/backcolor.vert b/src/glsl/webgl2/hips/raytracer/backcolor.vert index bab6fbd84..770e6018a 100644 --- a/src/glsl/webgl2/hips/raytracer/backcolor.vert +++ b/src/glsl/webgl2/hips/raytracer/backcolor.vert @@ -1,5 +1,5 @@ #version 300 es -precision highp float; +precision lowp float; precision mediump int; layout (location = 0) in vec2 pos_clip_space; diff --git a/src/glsl/webgl2/hips/raytracer/color.frag b/src/glsl/webgl2/hips/raytracer/color.frag index fe0894939..49920de68 100644 --- a/src/glsl/webgl2/hips/raytracer/color.frag +++ b/src/glsl/webgl2/hips/raytracer/color.frag @@ -1,10 +1,12 @@ #version 300 es -precision highp float; -precision highp sampler2D; -precision highp usampler2D; -precision highp isampler2D; +precision lowp float; +precision lowp sampler2DArray; +precision lowp usampler2DArray; +precision lowp isampler2DArray; precision mediump int; +uniform sampler2DArray tex; + in vec2 out_clip_pos; in vec3 frag_pos; out vec4 out_frag_color; @@ -30,22 +32,14 @@ vec4 get_tile_color(vec3 pos) { vec2 uv = vec2(result.dy, result.dx); Tile tile = textures_tiles[idx]; - int idx_texture = tile.texture_idx >> 6; - int off = tile.texture_idx & 0x3F; - float idx_row = float(off >> 3); // in [0; 7] - float idx_col = float(off & 0x7); // in [0; 7] - - vec2 offset = (vec2(idx_col, idx_row) + uv)*0.125; - vec3 UV = vec3(offset, float(idx_texture)); + vec2 offset = uv; + vec3 UV = vec3(offset, float(tile.texture_idx)); vec4 color = get_color_from_texture(UV); color.a *= (1.0 - tile.empty); return color; } -uniform sampler2D position_tex; -uniform mat4 model; - void main() { // Get the HEALPix cell idx and the uv in the texture vec4 c = get_tile_color(normalize(frag_pos)); diff --git a/src/glsl/webgl2/hips/raytracer/grayscale_to_colormap.frag b/src/glsl/webgl2/hips/raytracer/grayscale_to_colormap.frag index 9e1df2029..e5b426f5a 100644 --- a/src/glsl/webgl2/hips/raytracer/grayscale_to_colormap.frag +++ b/src/glsl/webgl2/hips/raytracer/grayscale_to_colormap.frag @@ -1,8 +1,8 @@ #version 300 es -precision highp float; -precision highp sampler2D; -precision highp usampler2D; -precision highp isampler2D; +precision lowp float; +precision lowp sampler2DArray; +precision lowp sampler2DArray; +precision lowp isampler2DArray; precision mediump int; in vec3 frag_pos; @@ -19,6 +19,8 @@ struct Tile { uniform Tile textures_tiles[12]; uniform float opacity; +uniform sampler2DArray tex; + struct TileColor { Tile tile; vec4 color; @@ -32,39 +34,18 @@ vec4 get_tile_color(vec3 pos) { HashDxDy result = hash_with_dxdy(0, pos.zxy); int idx = result.idx; - vec2 uv = vec2(result.dy, result.dx); - Tile tile = textures_tiles[idx]; - int idx_texture = tile.texture_idx >> 6; - int off = tile.texture_idx & 0x3F; - float idx_row = float(off >> 3); // in [0; 7] - float idx_col = float(off & 0x7); // in [0; 7] - - vec2 offset = (vec2(idx_col, idx_row) + uv)*0.125; - vec3 UV = vec3(offset, float(idx_texture)); + vec2 offset = uv; + vec3 UV = vec3(offset, float(tile.texture_idx)); vec4 color = get_colormap_from_grayscale_texture(UV); - // handle empty tiles - //vec4 c1 = mix(c, blank_color, tile.empty); - //vec4 c2 = mix(c, colormap_f(0.0), tile.empty); - //vec4 color = mix(c1, c2, first_survey); - // For empty tiles we set the alpha of the pixel to 0.0 - // so that what is behind will be plotted color.a *= (1.0 - tile.empty); return color; } -uniform sampler2D position_tex; -uniform mat4 model; - void main() { - /*vec2 uv = out_clip_pos * 0.5 + 0.5; - vec3 n = texture(position_tex, uv).rgb; - - vec3 frag_pos = vec3(model * vec4(n, 1.0));*/ - vec4 c = get_tile_color(normalize(frag_pos)); out_frag_color = c; out_frag_color.a = out_frag_color.a * opacity; diff --git a/src/glsl/webgl2/hips/raytracer/grayscale_to_colormap_i.frag b/src/glsl/webgl2/hips/raytracer/grayscale_to_colormap_i.frag index 88b0bb117..3c130c6ea 100644 --- a/src/glsl/webgl2/hips/raytracer/grayscale_to_colormap_i.frag +++ b/src/glsl/webgl2/hips/raytracer/grayscale_to_colormap_i.frag @@ -1,10 +1,12 @@ #version 300 es -precision highp float; -precision highp sampler2D; -precision highp usampler2D; -precision highp isampler2D; +precision lowp float; +precision lowp sampler2DArray; +precision lowp usampler2DArray; +precision lowp isampler2DArray; precision mediump int; +uniform isampler2DArray tex; + in vec3 frag_pos; in vec2 out_clip_pos; out vec4 out_frag_color; @@ -24,43 +26,21 @@ uniform float opacity; #include ../../projection/hpx.glsl; vec4 get_tile_color(vec3 pos) { - HashDxDy result = hash_with_dxdy(0, pos.zxy); +HashDxDy result = hash_with_dxdy(0, pos.zxy); int idx = result.idx; - vec2 uv = vec2(result.dy, result.dx); - Tile tile = textures_tiles[idx]; - int idx_texture = tile.texture_idx >> 6; - int off = tile.texture_idx & 0x3F; - float idx_row = float(off >> 3); // in [0; 7] - float idx_col = float(off & 0x7); // in [0; 7] - - vec2 offset = (vec2(idx_col, idx_row) + uv)*0.125; - vec3 UV = vec3(offset, float(idx_texture)); + vec2 offset = uv; + vec3 UV = vec3(offset, float(tile.texture_idx)); vec4 color = get_colormap_from_grayscale_texture(UV); - // handle empty tiles - //vec4 c1 = mix(c, blank_color, tile.empty); - //vec4 c2 = mix(c, colormap_f(0.0), tile.empty); - //vec4 color = mix(c1, c2, first_survey); - - // For empty tiles we set the alpha of the pixel to 0.0 - // so that what is behind will be plotted color.a *= (1.0 - tile.empty); return color; } -uniform sampler2D position_tex; -uniform mat4 model; - void main() { - /*vec2 uv = out_clip_pos * 0.5 + 0.5; - vec3 n = texture(position_tex, uv).rgb; - - vec3 frag_pos = vec3(model * vec4(n, 1.0));*/ - vec4 c = get_tile_color(normalize(frag_pos)); out_frag_color = c; out_frag_color.a = out_frag_color.a * opacity; diff --git a/src/glsl/webgl2/hips/raytracer/grayscale_to_colormap_u.frag b/src/glsl/webgl2/hips/raytracer/grayscale_to_colormap_u.frag index 7865d7c61..562f080f8 100644 --- a/src/glsl/webgl2/hips/raytracer/grayscale_to_colormap_u.frag +++ b/src/glsl/webgl2/hips/raytracer/grayscale_to_colormap_u.frag @@ -1,10 +1,12 @@ #version 300 es -precision highp float; -precision highp sampler2D; -precision highp usampler2D; -precision highp isampler2D; +precision lowp float; +precision lowp sampler2DArray; +precision lowp usampler2DArray; +precision lowp isampler2DArray; precision mediump int; +uniform usampler2DArray tex; + in vec3 frag_pos; in vec2 out_clip_pos; out vec4 out_frag_color; @@ -28,38 +30,17 @@ vec4 get_tile_color(vec3 pos) { int idx = result.idx; vec2 uv = vec2(result.dy, result.dx); - Tile tile = textures_tiles[idx]; - int idx_texture = tile.texture_idx >> 6; - int off = tile.texture_idx & 0x3F; - float idx_row = float(off >> 3); // in [0; 7] - float idx_col = float(off & 0x7); // in [0; 7] - - vec2 offset = (vec2(idx_col, idx_row) + uv)*0.125; - vec3 UV = vec3(offset, float(idx_texture)); + vec2 offset = uv; + vec3 UV = vec3(offset, float(tile.texture_idx)); vec4 color = get_colormap_from_grayscale_texture(UV); - // handle empty tiles - //vec4 c1 = mix(c, blank_color, tile.empty); - //vec4 c2 = mix(c, colormap_f(0.0), tile.empty); - //vec4 color = mix(c1, c2, first_survey); - - // For empty tiles we set the alpha of the pixel to 0.0 - // so that what is behind will be plotted color.a *= (1.0 - tile.empty); return color; } -uniform sampler2D position_tex; -uniform mat4 model; - void main() { - /*vec2 uv = out_clip_pos * 0.5 + 0.5; - vec3 n = texture(position_tex, uv).rgb; - - vec3 frag_pos = vec3(model * vec4(n, 1.0));*/ - vec4 c = get_tile_color(normalize(frag_pos)); out_frag_color = c; out_frag_color.a = out_frag_color.a * opacity; diff --git a/src/glsl/webgl2/hips/raytracer/raytracer.vert b/src/glsl/webgl2/hips/raytracer/raytracer.vert index 2dac7564f..2caa5582a 100644 --- a/src/glsl/webgl2/hips/raytracer/raytracer.vert +++ b/src/glsl/webgl2/hips/raytracer/raytracer.vert @@ -1,5 +1,5 @@ #version 300 es -precision highp float; +precision lowp float; precision mediump int; layout (location = 0) in vec2 pos_clip_space; @@ -14,7 +14,6 @@ uniform mat4 model; void main() { vec2 uv = pos_clip_space * 0.5 + 0.5; - //world_pos = check_inversed_longitude(world_pos); frag_pos = vec3(model * vec4(pos_world_space, 1.0)); diff --git a/src/glsl/webgl2/image/sampler.frag b/src/glsl/webgl2/image/sampler.frag index 5e0ab3b4a..6ec167d43 100644 --- a/src/glsl/webgl2/image/sampler.frag +++ b/src/glsl/webgl2/image/sampler.frag @@ -8,8 +8,6 @@ in vec2 frag_uv; uniform sampler2D tex; uniform float opacity; -#include ../hips/color.glsl; - void main() { out_frag_color = texture(tex, vec2(frag_uv.x, 1.0 - frag_uv.y)); out_frag_color.a = out_frag_color.a * opacity; diff --git a/src/glsl/webgl2/passes/post_fragment_100es.glsl b/src/glsl/webgl2/passes/post_fragment_100es.glsl deleted file mode 100644 index 2530a88b8..000000000 --- a/src/glsl/webgl2/passes/post_fragment_100es.glsl +++ /dev/null @@ -1,26 +0,0 @@ -#version 300 es -precision mediump float; - -in vec2 v_tc; -out vec4 color; - -uniform sampler2D fbo_tex; - -// 0-255 sRGB from 0-1 linear -vec3 srgb_from_linear(vec3 rgb) { - bvec3 cutoff = lessThan(rgb, vec3(0.0031308)); - vec3 lower = rgb * vec3(3294.6); - vec3 higher = vec3(269.025) * pow(rgb, vec3(1.0 / 2.4)) - vec3(14.025); - return mix(higher, lower, vec3(cutoff)); -} - -// 0-255 sRGBA from 0-1 linear -vec4 srgba_from_linear(vec4 rgba) { - return vec4(srgb_from_linear(rgba.rgb), 255.0 * rgba.a); -} - -void main() { - color = texture(fbo_tex, v_tc); - - //color = srgba_from_linear(color) / 255.; -} \ No newline at end of file diff --git a/src/glsl/webgl2/passes/post_vertex_100es.glsl b/src/glsl/webgl2/passes/post_vertex_100es.glsl deleted file mode 100644 index 1078e0ad4..000000000 --- a/src/glsl/webgl2/passes/post_vertex_100es.glsl +++ /dev/null @@ -1,10 +0,0 @@ -#version 300 es -precision mediump float; - -layout (location = 0) in vec2 a_pos; -out vec2 v_tc; - -void main() { - gl_Position = vec4(a_pos * 2. - 1., 0.0, 1.0); - v_tc = a_pos; -} \ No newline at end of file diff --git a/src/js/A.js b/src/js/A.js index bf3f48fa5..1ee99e4e3 100644 --- a/src/js/A.js +++ b/src/js/A.js @@ -1033,7 +1033,7 @@ A.init = (async () => { .createElement('canvas') .getContext('webgl2'); - await init(); + await init({}); // Check for webgl2 support if (isWebGL2Supported) { Aladin.wasmLibs.core = module; diff --git a/src/js/Aladin.js b/src/js/Aladin.js index e1449802b..812aed2c3 100644 --- a/src/js/Aladin.js +++ b/src/js/Aladin.js @@ -948,7 +948,7 @@ export let Aladin = (function () { }; /** - * Append a message to the status bar with a specific duration + * Append a message to the status bar * * @memberof Aladin * @param {Object} options - The message to display @@ -971,6 +971,18 @@ export let Aladin = (function () { } }; +/** + * Remove a message from the status bar + * + * @memberof Aladin + * @param {string} id - The id of the message to remove + */ + Aladin.prototype.removeStatusBarMessage = function (id) { + if (this.statusBar) { + this.statusBar.removeMessage(id); + } + }; + Aladin.prototype.getProjectionName = function () { const self = this; diff --git a/src/js/Catalog.js b/src/js/Catalog.js index 0d6872c11..f6f5d303b 100644 --- a/src/js/Catalog.js +++ b/src/js/Catalog.js @@ -490,6 +490,7 @@ export let Catalog = (function () { * @param {string} [options.color] - the color of the shape * @param {string} [options.selectionColor] - the color of the shape when selected * @param {number} [options.sourceSize] - size of the shape + * @param {string} [options.hoverColor=options.color] - the color to apply to sources in the catalog when they are hovered. * @param {string|Function|HTMLImageCanvas|HTMLImageElement} [options.shape="square"] - the type of the shape. Can be square, rhomb, plus, cross, triangle, circle. * A callback function can also be called that return an HTMLImageElement in function of the source object. A canvas or an image can also be given. * @param {string|Function} [options.onClick] - Whether the source data appears as a table row or a in popup. Can be 'showTable' string, 'showPopup' string or a custom user defined function that handles the click. @@ -498,6 +499,7 @@ export let Catalog = (function () { options = options || {}; this.color = options.color || this.color || Color.getNextColor(); this.selectionColor = options.selectionColor || this.selectionColor || Color.getNextColor(); + this.hoverColor = options.hoverColor || this.color; this.sourceSize = options.sourceSize || this.sourceSize || 6; this.shape = options.shape || this.shape || "square"; this.onClick = options.onClick || this.onClick; @@ -901,15 +903,27 @@ export let Catalog = (function () { let xy = this.view.wasm.worldToScreenVec(this.ra, this.dec); + let drawSource = (s, idx) => { + s.x = xy[2 * idx]; + s.y = xy[2 * idx + 1]; + + self.drawSource(s, ctx, width, height); + inside.push(s); + }; + let self = this; this.sources.forEach(function (s, idx) { if (xy[2 * idx] && xy[2 * idx + 1]) { - if (!self.filterFn || self.filterFn(s)) { - s.x = xy[2 * idx]; - s.y = xy[2 * idx + 1]; + if (self.filterFn) { + if(!self.filterFn(s)) { + s.hide() + } else { + s.show() - self.drawSource(s, ctx, width, height); - inside.push(s); + drawSource(s, idx) + } + } else { + drawSource(s, idx) } } }); diff --git a/src/js/FiniteStateMachine/CircleSelect.js b/src/js/FiniteStateMachine/CircleSelect.js index 4f887bf11..8777292c7 100644 --- a/src/js/FiniteStateMachine/CircleSelect.js +++ b/src/js/FiniteStateMachine/CircleSelect.js @@ -114,19 +114,27 @@ export class CircleSelect extends FSM { // execute selection callback only (typeof this.callback === 'function') && this.callback(s); - // TODO: remove these modes in the future + this.dispatch("off"); + }; + + let mouseout = mouseup; + + let off = () => { view.aladin.showReticle(true) view.setCursor('default'); view.setMode(View.PAN) view.requestRedraw(); - }; - let mouseout = mouseup; + view.aladin.removeStatusBarMessage('selector') + }; super({ - state: 'mouseup', + state: 'off', transitions: { + off: { + start, + }, start: { mousedown }, @@ -144,10 +152,10 @@ export class CircleSelect extends FSM { mouseout }, mouseout: { - start + off }, mouseup: { - start, + off, } } }) diff --git a/src/js/FiniteStateMachine/PolySelect.js b/src/js/FiniteStateMachine/PolySelect.js index b289374f6..d2a50cd96 100644 --- a/src/js/FiniteStateMachine/PolySelect.js +++ b/src/js/FiniteStateMachine/PolySelect.js @@ -38,7 +38,7 @@ export class PolySelect extends FSM { // constructor constructor(options, view) { // Off initial state - let off = () => { + let off = () => { view.aladin.showReticle(true) view.setMode(View.PAN) view.setCursor('default'); @@ -46,6 +46,8 @@ export class PolySelect extends FSM { // in case of a mouseout we would like to erase the selection draw // in the canvas view.requestRedraw(); + + view.aladin.removeStatusBarMessage('selector') } let btn; let mouseout = (params) => { @@ -143,6 +145,12 @@ export class PolySelect extends FSM { } let finish = () => { + if (this.coos.length <= 2) { + console.warn("Invalid selection, please draw at least a 3 vertices polygon") + this.dispatch("off") + return; + } + // finish the selection let xMin = this.coos[0].x let yMin = this.coos[0].y diff --git a/src/js/FiniteStateMachine/RectSelect.js b/src/js/FiniteStateMachine/RectSelect.js index 42164699c..ac4381eae 100644 --- a/src/js/FiniteStateMachine/RectSelect.js +++ b/src/js/FiniteStateMachine/RectSelect.js @@ -114,36 +114,57 @@ export class RectSelect extends FSM { callback(objList); } } + + this.dispatch('off'); + }; + + let off = () => { + view.aladin.showReticle(true) view.setMode(View.PAN) + view.setCursor('default'); + + // in case of a mouseout we would like to erase the selection draw + // in the canvas view.requestRedraw(); - }; + + view.aladin.removeStatusBarMessage('selector') + } let mouseout = mouseup; super({ - state: 'mouseup', + state: 'off', transitions: { + off: { + start, + }, start: { - mousedown + mousedown, + mouseup, + mouseout, + off }, mousedown: { - mousemove + mousemove, + off }, mousemove: { draw, mouseup, - mouseout + mouseout, + off }, draw: { mousemove, mouseup, - mouseout + mouseout, + off }, mouseout: { - start + off }, mouseup: { - start, + off, } } }) diff --git a/src/js/Overlay.js b/src/js/Overlay.js index aa747329c..fc961b7be 100644 --- a/src/js/Overlay.js +++ b/src/js/Overlay.js @@ -190,11 +190,11 @@ export let GraphicOverlay = (function() { // ajout d'un tableau d'overlays (= objets Footprint, Circle ou Polyline) GraphicOverlay.prototype.addFootprints = function(overlaysToAdd) { + overlaysToAdd = [].concat(overlaysToAdd) + for (var k=0, len=overlaysToAdd.length; k { + s.x = xy[2 * idx]; + s.y = xy[2 * idx + 1]; + + self.drawSource(s, ctx, width, height); + }; + sources.forEach(function(s, idx) { - if (xy[2*idx] && xy[2*idx + 1]) { - if (!self.filterFn || self.filterFn(s)) { - s.x = xy[2*idx]; - s.y = xy[2*idx + 1]; + if (xy[2 * idx] && xy[2 * idx + 1]) { + if (self.filterFn) { + if(!self.filterFn(s)) { + s.hide() + } else { + s.show() - self.drawSource(s, ctx, width, height) + drawSource(s, idx) + } + } else { + drawSource(s, idx) } } }); diff --git a/src/js/Selector.js b/src/js/Selector.js index 6ec015cd7..aef39284e 100644 --- a/src/js/Selector.js +++ b/src/js/Selector.js @@ -78,6 +78,21 @@ export class Selector { } } + start(mode, callback) { + this.setMode(mode); + this.dispatch('start', {callback}) + + this.view.aladin.addStatusBarMessage({ + id: 'selector', + message: 'You entered the selection mode', + type: 'info' + }) + } + + cancel() { + this.dispatch('off') + } + dispatch(to, params) { this.select.dispatch(to, params); } diff --git a/src/js/View.js b/src/js/View.js index d9539ca90..aabca3e2a 100644 --- a/src/js/View.js +++ b/src/js/View.js @@ -436,8 +436,7 @@ export let View = (function () { } View.prototype.startSelection = function(mode, callback) { - this.selector.setMode(mode); - this.selector.dispatch('start', {callback}); + this.selector.start(mode, callback); } View.prototype.setMode = function (mode) { @@ -789,7 +788,7 @@ export let View = (function () { view.selector.dispatch('mouseup', {coo: xymouse}) } }); - + // reacting on 'click' rather on 'mouseup' is more reliable when panning the view Utils.on(view.catalogCanvas, "click mouseout touchend touchcancel", function (e) { const xymouse = Utils.relMouseCoords(e); @@ -1130,7 +1129,7 @@ export let View = (function () { }); //// endof mousemove //// // disable text selection on IE - Utils.on(view.aladinDiv, "selectstart", function () { return false; }) + //Utils.on(view.aladinDiv, "selectstart", function () { return false; }) var eventCount = 0; var eventCountStart; var isTouchPad; @@ -1245,6 +1244,36 @@ export let View = (function () { return false; }); + + Utils.on(view.catalogCanvas, "mouseover", (_) => { + view.mouseover = true; + }); + + Utils.on(view.catalogCanvas, "mouseout", (_) => { + view.mouseover = false; + }); + + Utils.on(window, "keydown", function (e) { + // check first if the user mouse over the aladin div + if (!view.mouseover) + return; + + switch (e.keyCode) { + // shift + case 16: + view.aladin.select('rect', (selection) => { + view.selectObjects(selection); + }) + break; + // escape + case 27: + view.selector.cancel() + break; + default: + break; + + } + }); }; var init = function (view) { @@ -1286,6 +1315,7 @@ export let View = (function () { */ View.prototype.redraw = function (timestamp) { // request another frame + requestAnimFrame(this.redrawClbk); // Elapsed time since last loop const now = performance.now(); @@ -1309,7 +1339,6 @@ export let View = (function () { this.needRedraw = false; //this.then = now % View.FPS_INTERVAL; - requestAnimFrame(this.redrawClbk); }; View.prototype.drawAllOverlays = function () { diff --git a/src/js/shapes/Vector.js b/src/js/shapes/Vector.js index cf1d6b16e..d2ee0d9f2 100644 --- a/src/js/shapes/Vector.js +++ b/src/js/shapes/Vector.js @@ -175,9 +175,9 @@ export let Vector = (function() { isInStroke: Ellipse.prototype.isInStroke, - /*Line.prototype.intersectsBBox = function(x, y, w, h) { + intersectsBBox: function(x, y, w, h) { // todo - };*/ + }, }; return Vector; diff --git a/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-chromium-darwin.jpg b/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-chromium-darwin.jpg index fe15c4e24..ac79c5851 100644 Binary files a/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-chromium-darwin.jpg and b/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-chromium-darwin.jpg differ diff --git a/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-webkit-darwin.jpg b/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-webkit-darwin.jpg index 0d80331d9..4b40de189 100644 Binary files a/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-webkit-darwin.jpg and b/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-webkit-darwin.jpg differ