JPEG case: draw black when the tile is missing

This commit is contained in:
bmatthieu3
2025-03-05 11:00:19 +01:00
committed by Matthieu Baumann
parent 3f248a82ea
commit 5f9c9d9154
6 changed files with 62 additions and 39 deletions

View File

@@ -20,6 +20,7 @@ use crate::{
tile_fetcher::TileFetcherQueue,
time::DeltaTime,
};
use al_core::image::format::ChannelType;
use wcs::WCS;
use wasm_bindgen::prelude::*;
@@ -702,7 +703,7 @@ impl App {
tile_copied = true;
match hips {
HiPS::D2(hips) => {
hips.add_tile(&tile.cell, img, tile.time_req)?
hips.add_tile(&tile.cell, Some(img), tile.time_req)?
}
HiPS::D3(hips) => hips.add_tile(
&tile.cell,
@@ -711,10 +712,19 @@ impl App {
tile.channel.unwrap() as u16,
)?,
}
self.time_start_blending = Time::now();
}
None => (),
},
// In case of JPEG tile missing, add it to the HiPS because it must be drawn as black
None if cfg.get_format().get_channel() == ChannelType::RGB8U => {
self.request_redraw = true;
match hips {
HiPS::D2(hips) => {
hips.add_tile::<ImageType>(&tile.cell, None, tile.time_req)?
}
HiPS::D3(_) => (),
}
},
_ => ()
};
}
}

View File

@@ -196,7 +196,7 @@ impl HiPS2DBuffer {
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)?;
self.push(&HEALPixCell(depth_tile, idx as u64), Some(image), time_req)?;
}
}
@@ -272,7 +272,7 @@ impl HiPS2DBuffer {
pub fn push<I: Image>(
&mut self,
cell: &HEALPixCell,
image: I,
image: Option<I>,
time_request: Time,
) -> Result<(), JsValue> {
if !self.contains_tile(cell) {
@@ -331,14 +331,16 @@ impl HiPS2DBuffer {
&mut self.base_textures[idx as usize]
};
send_to_gpu(
cell,
texture,
image,
&self.texture_2d_array,
&mut self.config,
)?;
if let Some(image) = image {
send_to_gpu(
cell,
texture,
image,
&self.texture_2d_array,
&mut self.config,
)?;
}
texture.append(
cell, // The tile cell
&self.config,

View File

@@ -417,18 +417,14 @@ impl HiPS2D {
for cell in &self.hpx_cells_in_view {
// filter textures that are not in the moc
let cell = if let Some(moc) = self.footprint_moc.as_ref() {
if moc.intersects_cell(&cell) {
if moc.intersects_cell(&cell) || channel == ChannelType::RGB8U {
// Rasterizer does not render tiles that are not in the MOC
// This is not a problem for transparency rendered HiPses (FITS or PNG)
// but JPEG tiles do have black when no pixels data is found
// We therefore must draw in black for the tiles outside the HiPS MOC
Some(&cell)
} else {
if channel == ChannelType::RGB8U {
// Rasterizer does not render tiles that are not in the MOC
// This is not a problem for transparency rendered HiPses (FITS or PNG)
// but JPEG tiles do have black when no pixels data is found
// We therefore must draw in black for the tiles outside the HiPS MOC
Some(&cell)
} else {
None
}
None
}
} else {
Some(&cell)
@@ -627,7 +623,7 @@ impl HiPS2D {
pub fn add_tile<I: Image>(
&mut self,
cell: &HEALPixCell,
image: I,
image: Option<I>,
time_request: Time,
) -> Result<(), JsValue> {
self.buffer.push(&cell, image, time_request)

View File

@@ -182,6 +182,7 @@ impl<'a> HpxTexture2DUniforms<'a> {
use al_core::shader::{SendUniforms, ShaderBound};
impl<'a> SendUniforms for HpxTexture2DUniforms<'a> {
// Info: These uniforms are used for raytracing drawing mode only
fn attach_uniforms<'b>(&self, shader: &'b ShaderBound<'b>) -> &'b ShaderBound<'b> {
shader
.attach_uniform(&format!("{}{}", self.name, "uniq"), &self.texture.uniq)
@@ -191,8 +192,12 @@ impl<'a> SendUniforms for HpxTexture2DUniforms<'a> {
)
.attach_uniform(
&format!("{}{}", self.name, "empty"),
//&((self.texture.full as u8) as f32),
&0.0,
// This is useful for FITS tiles only because:
// - for JPEG, missing tiles are inserted in the buffer and black is drawn
// - for PNG, tiles are not inserted but default color chosen is fully transparent (might be vec4(0.0, 0.0, 0.0, 0.0))
//
// Therefore for FITS files we must indicate GPU which base tiles are missing so that we draw fully transparent pixels
&((!self.texture.full as u8) as f32),
)
.attach_uniform(
&format!("{}{}", self.name, "start_time"),

View File

@@ -219,23 +219,33 @@ impl Layers {
// Check whether a hips to plot is allsky
// if neither are, we draw a font
// if there are, we do not draw nothing
let render_background_color = !self.layers.iter().any(|layer| {
let mut background_color = None;
for layer in self.layers.iter() {
let meta = self.meta.get(layer).unwrap_abort();
let cdid = self.ids.get(layer).unwrap_abort();
if let Some(hips) = self.hipses.get(cdid) {
let hips_cfg = hips.get_config();
(hips.is_allsky() || hips_cfg.get_format().get_channel() == ChannelType::RGB8U)
&& meta.opacity == 1.0
let allsky = hips.is_allsky();
let opaque = meta.opacity == 1.0;
background_color = match (allsky, opaque) {
(true, true) => None,
_ => Some(self.background_color),
};
} else {
// image fits case
false
// image fits case. We render a background
background_color = Some(self.background_color);
}
});
if background_color.is_some() {
break;
}
}
// Need to render transparency font
if render_background_color {
let background_color = &self.background_color;
if let Some(background_color) = &background_color {
let vao = if raytracing {
raytracer.get_vao()
} else {
@@ -275,8 +285,8 @@ impl Layers {
}
}
let rendered_layers = &self.layers[idx_start_layer..];
for layer in rendered_layers {
let layers_to_render = &self.layers[idx_start_layer..];
for layer in layers_to_render {
let draw_opt = self.meta.get(layer).expect("Meta should be found");
if draw_opt.visible() {
// 1. Update the hips if necessary

View File

@@ -26,7 +26,7 @@ uniform float opacity;
#include ../../projection/hpx_proj.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);