diff --git a/CHANGELOG.md b/CHANGELOG.md index 50c2e3f6..a3e0894b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ All notable changes to this project will be documented in this file. - Draw unsupported chars with a font does not panic anymore. - Added `WindowConfig::window_icon` and `WindowConfig::taskbar_icon` to add icons for windows os. - Added example `egui_custom_font.rs`. +- Fix images loaded from files can set the texture format other rgba. +- Added `TextureFormat::Rgba32Float`. +- Avoid some allocations when textures are loaded. ## v0.8.0 - 28/11/2022 diff --git a/crates/notan_glow/src/lib.rs b/crates/notan_glow/src/lib.rs index dba758f4..c1b64019 100644 --- a/crates/notan_glow/src/lib.rs +++ b/crates/notan_glow/src/lib.rs @@ -585,7 +585,7 @@ impl DeviceBackend for GlowBackend { .bind_texture(glow::TEXTURE_2D, Some(texture.texture)); self.gl.pixel_store_i32( glow::UNPACK_ALIGNMENT, - opts.format.bytes_per_pixel() as _, + opts.format.bytes_per_pixel().min(8) as _, ); match source { diff --git a/crates/notan_glow/src/texture.rs b/crates/notan_glow/src/texture.rs index f1f08f9a..30d8ff90 100644 --- a/crates/notan_glow/src/texture.rs +++ b/crates/notan_glow/src/texture.rs @@ -85,7 +85,7 @@ pub(crate) unsafe fn pre_create_texture<'a>( let texture = gl.create_texture()?; - let bytes_per_pixel = info.bytes_per_pixel() as _; + let bytes_per_pixel = info.bytes_per_pixel().min(8) as _; gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, bytes_per_pixel); gl.bind_texture(glow::TEXTURE_2D, Some(texture)); @@ -197,6 +197,7 @@ pub(crate) unsafe fn create_texture( pub(crate) fn texture_type(tf: &TextureFormat) -> u32 { match tf { TextureFormat::R32Float => glow::FLOAT, + TextureFormat::Rgba32Float => glow::FLOAT, TextureFormat::R32Uint => glow::UNSIGNED_INT, TextureFormat::R16Uint => glow::UNSIGNED_SHORT, TextureFormat::Depth16 => glow::UNSIGNED_SHORT, @@ -207,6 +208,7 @@ pub(crate) fn texture_type(tf: &TextureFormat) -> u32 { pub(crate) fn texture_format(tf: &TextureFormat) -> u32 { match tf { TextureFormat::Rgba32 => glow::RGBA, + TextureFormat::Rgba32Float => RGBA, TextureFormat::R8 => glow::RED, TextureFormat::R8Uint => glow::RED_INTEGER, TextureFormat::R16Uint => glow::RED_INTEGER, @@ -225,6 +227,7 @@ pub(crate) fn texture_internal_format(tf: &TextureFormat) -> u32 { TextureFormat::R32Float => glow::R32F, TextureFormat::R32Uint => glow::R32UI, TextureFormat::SRgba8 => glow::SRGB8_ALPHA8, + TextureFormat::Rgba32Float => glow::RGBA32F, _ => texture_format(tf), } } diff --git a/crates/notan_glow/src/texture_source.rs b/crates/notan_glow/src/texture_source.rs index 735ef912..30d7ec88 100644 --- a/crates/notan_glow/src/texture_source.rs +++ b/crates/notan_glow/src/texture_source.rs @@ -1,4 +1,4 @@ -use crate::texture::create_texture; +use crate::texture::{create_texture, TextureKey}; use crate::GlowBackend; use notan_graphics::color::Color; use notan_graphics::{TextureFormat, TextureInfo}; @@ -17,25 +17,52 @@ pub(crate) fn add_texture_from_image( buffer: Vec, mut info: TextureInfo, ) -> Result<(u64, TextureInfo), String> { - let data = image::load_from_memory(&buffer) - .map_err(|e| e.to_string())? - .to_rgba8(); - - let pixels = if info.premultiplied_alpha { - premultiplied_alpha(&data) - } else { - data.to_vec() - }; - - info.format = TextureFormat::Rgba32; - info.width = data.width() as _; - info.height = data.height() as _; - - let tex = unsafe { create_texture(&backend.gl, Some(&pixels), &info)? }; + let img = image::load_from_memory(&buffer).map_err(|e| e.to_string())?; + let tex = parse_image(backend, &img, &mut info)?; let id = backend.add_inner_texture(tex, &info)?; Ok((id, info)) } +fn parse_image( + backend: &mut GlowBackend, + img: &image::DynamicImage, + info: &mut TextureInfo, +) -> Result { + // TODO process the loading of more texture types directly? + match info.format { + TextureFormat::Rgba32Float => { + let mut data = img.to_rgba32f(); + let width = data.width() as _; + let height = data.height() as _; + if info.premultiplied_alpha { + data.pixels_mut().for_each(|rgba| { + rgba.0 = Color::from(rgba.0).to_premultiplied_alpha().into(); + }); + } + info.width = width; + info.height = height; + let tex = + unsafe { create_texture(&backend.gl, Some(bytemuck::cast_slice(&data)), info)? }; + Ok(tex) + } + _ => { + let mut data = img.to_rgba8(); + let width = data.width() as _; + let height = data.height() as _; + if info.premultiplied_alpha { + data.pixels_mut().for_each(|rgba| { + rgba.0 = Color::from(rgba.0).to_premultiplied_alpha().into(); + }); + } + info.width = width; + info.height = height; + let tex = + unsafe { create_texture(&backend.gl, Some(bytemuck::cast_slice(&data)), info)? }; + Ok(tex) + } + } +} + pub(crate) fn add_texture_from_bytes( backend: &mut GlowBackend, bytes: Vec, diff --git a/crates/notan_graphics/src/texture.rs b/crates/notan_graphics/src/texture.rs index f667cdd0..094cbdb9 100644 --- a/crates/notan_graphics/src/texture.rs +++ b/crates/notan_graphics/src/texture.rs @@ -81,6 +81,7 @@ impl TextureFormat { R8 => 1, R8Uint => 1, R16Uint => 2, + Rgba32Float => 4 * 4, _ => 4, } } @@ -250,6 +251,7 @@ pub enum TextureFormat { R32Float, R32Uint, Depth16, + Rgba32Float, } #[derive(Debug, Clone, Copy, Eq, PartialEq)]