Skip to content

Commit 25d4ced

Browse files
enable easier modification of image samplers in image loaders (#22042)
# Objective Previously, to modify a sampler when loading an image with settings it was required to set all fields individually. Much of the time, these settings are all the same so to enable repeating textures you have to set the address_mode 3 times. To set filters you have to set them another 3 times. ```rust MeshMaterial3d(materials.add( StandardMaterial { base_color_texture: Some( asset_server.load_with_settings( "floor_graph_base_color.png", |settings: &mut ImageLoaderSettings| { let descriptor = settings.sampler.get_or_init_descriptor(); descriptor.address_mode_u = bevy::image::ImageAddressMode::Repeat; descriptor.address_mode_v = bevy::image::ImageAddressMode::Repeat; descriptor.address_mode_w = bevy::image::ImageAddressMode::Repeat; descriptor.mag_filter = ImageFilterMode::Linear; descriptor.min_filter = ImageFilterMode::Linear; descriptor.mipmap_filter = ImageFilterMode::Linear; } ), ), unlit: true, cull_mode: None, uv_transform: Affine2::from_scale(Vec2::new(30., 90.)), ..default() }, )), ``` ## Solution Add two new helpers, loosely modeled after the `Transform::with_<field>` functions. Further modifications can still be made to the descriptor for use cases which want to set one of the three fields differently, or additionally set anisotropy_clamp, etc. ```rust let descriptor = settings .sampler .get_or_init_descriptor() .set_address_mode(ImageAddressMode::Repeat) .set_filter(ImageFilterMode::Linear); ``` ## Testing New test in bevy_image ## Showcase ```rust MeshMaterial3d(materials.add( StandardMaterial { base_color_texture: Some( asset_server.load_with_settings( "floor_graph_base_color.png", |settings: &mut ImageLoaderSettings| { let descriptor = settings .sampler .get_or_init_descriptor() .set_address_mode(ImageAddressMode::Repeat) .set_filter(ImageFilterMode::Linear); } ), ), unlit: true, cull_mode: None, uv_transform: Affine2::from_scale(Vec2::new(30., 90.)), ..default() }, )), ``` This PR now includes: - `set_filter` - `set_address_mode` - `set_anisotropic_filter` --------- Co-authored-by: Greeble <166992735+greeble-dev@users.noreply.github.com>
1 parent ad1c38a commit 25d4ced

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

crates/bevy_image/src/image.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,36 @@ impl ImageSamplerDescriptor {
699699
}
700700
}
701701

702+
/// Returns this sampler descriptor with a new `ImageFilterMode` min, mag, and mipmap filters
703+
#[inline]
704+
pub fn set_filter(&mut self, filter: ImageFilterMode) -> &mut Self {
705+
self.mag_filter = filter;
706+
self.min_filter = filter;
707+
self.mipmap_filter = filter;
708+
self
709+
}
710+
711+
/// Returns this sampler descriptor with a new `ImageAddressMode` for u, v, and w
712+
#[inline]
713+
pub fn set_address_mode(&mut self, address_mode: ImageAddressMode) -> &mut Self {
714+
self.address_mode_u = address_mode;
715+
self.address_mode_v = address_mode;
716+
self.address_mode_w = address_mode;
717+
self
718+
}
719+
720+
/// Returns this sampler descriptor with an `anisotropy_clamp` value and also
721+
/// set filters to `ImageFilterMode::Linear`, which is required to
722+
/// use anisotropy.
723+
#[inline]
724+
pub fn set_anisotropic_filter(&mut self, anisotropy_clamp: u16) -> &mut Self {
725+
self.mag_filter = ImageFilterMode::Linear;
726+
self.min_filter = ImageFilterMode::Linear;
727+
self.mipmap_filter = ImageFilterMode::Linear;
728+
self.anisotropy_clamp = anisotropy_clamp;
729+
self
730+
}
731+
702732
pub fn as_wgpu(&self) -> SamplerDescriptor<Option<&str>> {
703733
SamplerDescriptor {
704734
label: self.label.as_deref(),
@@ -2212,4 +2242,34 @@ mod test {
22122242

22132243
assert!(image.data.as_ref().unwrap().iter().all(|&p| p == 255));
22142244
}
2245+
2246+
#[test]
2247+
fn get_or_init_sampler_modifications() {
2248+
// given some sampler
2249+
let mut default_sampler = ImageSampler::Default;
2250+
// a load_with_settings call wants to customize the descriptor
2251+
let my_sampler_in_a_loader = default_sampler
2252+
.get_or_init_descriptor()
2253+
.set_filter(ImageFilterMode::Linear)
2254+
.set_address_mode(ImageAddressMode::Repeat);
2255+
2256+
assert_eq!(
2257+
my_sampler_in_a_loader.address_mode_u,
2258+
ImageAddressMode::Repeat
2259+
);
2260+
assert_eq!(my_sampler_in_a_loader.min_filter, ImageFilterMode::Linear);
2261+
}
2262+
2263+
#[test]
2264+
fn get_or_init_sampler_anisotropy() {
2265+
// given some sampler
2266+
let mut default_sampler = ImageSampler::Default;
2267+
// a load_with_settings call wants to customize the descriptor
2268+
let my_sampler_in_a_loader = default_sampler
2269+
.get_or_init_descriptor()
2270+
.set_anisotropic_filter(8);
2271+
2272+
assert_eq!(my_sampler_in_a_loader.min_filter, ImageFilterMode::Linear);
2273+
assert_eq!(my_sampler_in_a_loader.anisotropy_clamp, 8);
2274+
}
22152275
}

0 commit comments

Comments
 (0)