From 3cc86d2ea27743cc5eab14ea5a5bf7149585a0e9 Mon Sep 17 00:00:00 2001 From: Dan Lock Date: Fri, 2 Feb 2024 23:46:00 +0000 Subject: [PATCH 1/4] Add TextureWrapMode to TextureOptions --- crates/egui-wgpu/src/renderer.rs | 7 +++++ crates/egui/src/lib.rs | 2 +- crates/egui_glow/src/painter.rs | 18 ++++++++++-- crates/epaint/src/textures.rs | 47 ++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/crates/egui-wgpu/src/renderer.rs b/crates/egui-wgpu/src/renderer.rs index 21227ef9058..bb0d4581cf2 100644 --- a/crates/egui-wgpu/src/renderer.rs +++ b/crates/egui-wgpu/src/renderer.rs @@ -923,12 +923,19 @@ fn create_sampler( epaint::textures::TextureFilter::Nearest => wgpu::FilterMode::Nearest, epaint::textures::TextureFilter::Linear => wgpu::FilterMode::Linear, }; + let address_mode = match options.wrap_mode { + epaint::textures::TextureWrapMode::ClampToEdge => wgpu::AddressMode::ClampToEdge, + epaint::textures::TextureWrapMode::Repeat => wgpu::AddressMode::Repeat, + epaint::textures::TextureWrapMode::MirroredRepeat => wgpu::AddressMode::MirrorRepeat, + }; device.create_sampler(&wgpu::SamplerDescriptor { label: Some(&format!( "egui sampler (mag: {mag_filter:?}, min {min_filter:?})" )), mag_filter, min_filter, + address_mode_u: address_mode, + address_mode_v: address_mode, ..Default::default() }) } diff --git a/crates/egui/src/lib.rs b/crates/egui/src/lib.rs index 73d51561d2d..ad931885ea8 100644 --- a/crates/egui/src/lib.rs +++ b/crates/egui/src/lib.rs @@ -395,7 +395,7 @@ pub use emath::{ pub use epaint::{ mutex, text::{FontData, FontDefinitions, FontFamily, FontId, FontTweak}, - textures::{TextureFilter, TextureOptions, TexturesDelta}, + textures::{TextureFilter, TextureOptions, TextureWrapMode, TexturesDelta}, ClippedPrimitive, ColorImage, FontImage, ImageData, Mesh, PaintCallback, PaintCallbackInfo, Rounding, Shape, Stroke, TextureHandle, TextureId, }; diff --git a/crates/egui_glow/src/painter.rs b/crates/egui_glow/src/painter.rs index 48c90050a20..c287bd7d251 100644 --- a/crates/egui_glow/src/painter.rs +++ b/crates/egui_glow/src/painter.rs @@ -33,6 +33,19 @@ impl TextureFilterExt for egui::TextureFilter { } } } +trait TextureWrapModeExt { + fn glow_code(&self) -> u32; +} + +impl TextureWrapModeExt for egui::TextureWrapMode { + fn glow_code(&self) -> u32 { + match self { + Self::ClampToEdge => glow::CLAMP_TO_EDGE, + Self::Repeat => glow::REPEAT, + Self::MirroredRepeat => glow::MIRRORED_REPEAT, + } + } +} #[derive(Debug)] pub struct PainterError(String); @@ -551,16 +564,15 @@ impl Painter { glow::TEXTURE_MIN_FILTER, options.minification.glow_code() as i32, ); - self.gl.tex_parameter_i32( glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, - glow::CLAMP_TO_EDGE as i32, + options.wrap_mode.glow_code() as i32, ); self.gl.tex_parameter_i32( glow::TEXTURE_2D, glow::TEXTURE_WRAP_T, - glow::CLAMP_TO_EDGE as i32, + options.wrap_mode.glow_code() as i32, ); check_for_gl_error!(&self.gl, "tex_parameter"); diff --git a/crates/epaint/src/textures.rs b/crates/epaint/src/textures.rs index e1979507b9f..c7603dba847 100644 --- a/crates/epaint/src/textures.rs +++ b/crates/epaint/src/textures.rs @@ -156,6 +156,9 @@ pub struct TextureOptions { /// How to filter when minifying (when texels are smaller than pixels). pub minification: TextureFilter, + + /// How to wrap the texture when the texture coordinates are outside the [0, 1] range. + pub wrap_mode: TextureWrapMode, } impl TextureOptions { @@ -163,12 +166,42 @@ impl TextureOptions { pub const LINEAR: Self = Self { magnification: TextureFilter::Linear, minification: TextureFilter::Linear, + wrap_mode: TextureWrapMode::ClampToEdge, }; /// Nearest magnification and minification. pub const NEAREST: Self = Self { magnification: TextureFilter::Nearest, minification: TextureFilter::Nearest, + wrap_mode: TextureWrapMode::ClampToEdge, + }; + + /// Linear magnification and minification, but with the texture repeated. + pub const LINEAR_REPEAT: Self = Self { + magnification: TextureFilter::Linear, + minification: TextureFilter::Linear, + wrap_mode: TextureWrapMode::Repeat, + }; + + /// Linear magnification and minification, but with the texture mirrored and repeated. + pub const LINEAR_MIRRORED_REPEAT: Self = Self { + magnification: TextureFilter::Linear, + minification: TextureFilter::Linear, + wrap_mode: TextureWrapMode::MirroredRepeat, + }; + + /// Nearest magnification and minification, but with the texture repeated. + pub const NEAREST_REPEAT: Self = Self { + magnification: TextureFilter::Nearest, + minification: TextureFilter::Nearest, + wrap_mode: TextureWrapMode::Repeat, + }; + + /// Nearest magnification and minification, but with the texture mirrored and repeated. + pub const NEAREST_MIRRORED_REPEAT: Self = Self { + magnification: TextureFilter::Nearest, + minification: TextureFilter::Nearest, + wrap_mode: TextureWrapMode::MirroredRepeat, }; } @@ -193,6 +226,20 @@ pub enum TextureFilter { Linear, } +/// Defines how textures are wrapped around objects when texture coordinates fall outside the [0, 1] range. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +pub enum TextureWrapMode { + /// Stretches the edge pixels to fill beyond the texture's bounds. + ClampToEdge, + + /// Tiles the texture across the surface, repeating it horizontally and vertically. + Repeat, + + /// Mirrors the texture with each repetition, creating symmetrical tiling. + MirroredRepeat, +} + // ---------------------------------------------------------------------------- /// What has been allocated and freed during the last period. From 6e3e46a941003454fa2eda195794fdf3af5f2493 Mon Sep 17 00:00:00 2001 From: Dan Lock Date: Fri, 2 Feb 2024 23:47:02 +0000 Subject: [PATCH 2/4] Add missing new line --- crates/egui_glow/src/painter.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/egui_glow/src/painter.rs b/crates/egui_glow/src/painter.rs index c287bd7d251..617d989295a 100644 --- a/crates/egui_glow/src/painter.rs +++ b/crates/egui_glow/src/painter.rs @@ -33,6 +33,7 @@ impl TextureFilterExt for egui::TextureFilter { } } } + trait TextureWrapModeExt { fn glow_code(&self) -> u32; } From 9ae890dd1e217d5fd18760d6dd8860ea58bf165f Mon Sep 17 00:00:00 2001 From: Dan Lock Date: Fri, 2 Feb 2024 23:55:35 +0000 Subject: [PATCH 3/4] Readded accidentally removed newline --- crates/egui_glow/src/painter.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/egui_glow/src/painter.rs b/crates/egui_glow/src/painter.rs index 617d989295a..b1278ac39d5 100644 --- a/crates/egui_glow/src/painter.rs +++ b/crates/egui_glow/src/painter.rs @@ -565,6 +565,7 @@ impl Painter { glow::TEXTURE_MIN_FILTER, options.minification.glow_code() as i32, ); + self.gl.tex_parameter_i32( glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, From 56b2faed8bde15c413574f6ecfb1865baf7db7d6 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 5 Feb 2024 08:43:32 +0100 Subject: [PATCH 4/4] Make `TextureWrapMode::ClampToEdge` the default --- crates/epaint/src/textures.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/epaint/src/textures.rs b/crates/epaint/src/textures.rs index c7603dba847..e4661ff02b7 100644 --- a/crates/epaint/src/textures.rs +++ b/crates/epaint/src/textures.rs @@ -227,10 +227,13 @@ pub enum TextureFilter { } /// Defines how textures are wrapped around objects when texture coordinates fall outside the [0, 1] range. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum TextureWrapMode { /// Stretches the edge pixels to fill beyond the texture's bounds. + /// + /// This is what you want to use for a normal image in a GUI. + #[default] ClampToEdge, /// Tiles the texture across the surface, repeating it horizontally and vertically.