Skip to content

Conversation

@ChristopherBiscardi
Copy link
Contributor

@ChristopherBiscardi ChristopherBiscardi commented Dec 6, 2025

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.

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.

let descriptor = settings
    .sampler
    .get_or_init_descriptor()
    .set_address_mode(ImageAddressMode::Repeat)
    .set_filter(ImageFilterMode::Linear);

Testing

New test in bevy_image

Showcase

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

@ChristopherBiscardi ChristopherBiscardi added A-Rendering Drawing game state to the screen S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Dec 6, 2025
Copy link
Contributor

@greeble-dev greeble-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clicking approve, but added a couple of optional suggestions/nitpicks.

I'm mildly negative on lumping mipmap_filter in with other filters since it's kinda orthogonal, but not a big deal. I guess "set everything to linear" is the most common case.

For bonus points, could also add anisotropy?

pub fn with_anisotropic_filter(&mut self, anisotropy_clamp: u16) -> &mut Self {
    self.with_filter(ImageFilterMode::Linear);
    self.anisotropy_clamp = anisotropy_clamp;
    self
}

}

/// Returns this sampler descriptor with a new `ImageFilterMode` min, mag, and mipmap filters
#[inline]
Copy link
Contributor

@greeble-dev greeble-dev Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#[inline]

I don't think inline is appropriate here. I respect that some other functions in the struct are inline, but they're probably from the olden days when inline was more necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're probably right. But out of curiosity, the compiler wouldn't inline this since it would always be used across a crate boundary right (without LTO)? So if this were being applied on a huge set of images it might be slower without the inline?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was true in the past, but since Rust 1.75 (2023/12) smaller functions are automatically tagged as cross-crate inlineable even without LTO.

So my personal preference is to let the compiler decide for these kinds of cases. But I don't think it's a big deal if the function is small and someone wants to add an inline hint to make sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to match the rest of the file for this PR and do an inline removal on all of these in a future PR instead.

@greeble-dev greeble-dev added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it C-Usability A targeted quality-of-life change that makes Bevy easier to use and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Dec 6, 2025
ChristopherBiscardi and others added 6 commits December 6, 2025 18:53
Co-authored-by: Greeble <[email protected]>
The `with_` prefix is mostly used for copies, which these functions don't do.
The `set_` prefix has precedence for returning `&mut App`.
@ChristopherBiscardi
Copy link
Contributor Author

I have finished addressing review comments, and it is ready for final review

@ChristopherBiscardi ChristopherBiscardi added this to the 0.18 milestone Dec 7, 2025
@mockersf mockersf added this pull request to the merge queue Dec 7, 2025
Merged via the queue into bevyengine:main with commit 25d4ced Dec 7, 2025
36 checks passed
@github-project-automation github-project-automation bot moved this to Done in Rendering Dec 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Rendering Drawing game state to the screen C-Usability A targeted quality-of-life change that makes Bevy easier to use S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants