Skip to content

Commit e663d45

Browse files
TextureAtlasBuilder padding (#9494)
# Objective `TextureAtlas` supports pregenerated texture atlases with padding, but `TextureAtlasBuilder` can't add padding when it creates a new atlas. fixes #8150 ## Solution Add a method `padding` to `TextureAtlasBuilder` that sets the amount of padding to add around each texture. When queueing the textures to be copied, add the padding value to the size of each source texture. Then when copying the source textures to the output atlas texture subtract the same padding value from the sizes of the target rects. unpadded: <img width="961" alt="texture_atlas_example" src="https://github.com/bevyengine/bevy/assets/27962798/8cf02442-dc3e-4429-90f1-543bc9270d8b"> padded: <img width="961" alt="texture_atlas_example_with_padding" src="https://github.com/bevyengine/bevy/assets/27962798/da347bcc-b083-4650-ba0c-86883853764f"> --- ## Changelog `TextureAtlasBuilder` * Added support for building texture atlases with padding. * Adds a `padding` method to `TextureAtlasBuilder` that can be used to set an amount of padding to add between the sprites of the generated texture atlas. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
1 parent 73447b6 commit e663d45

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed

crates/bevy_sprite/src/texture_atlas_builder.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bevy_asset::{AssetId, Assets};
22
use bevy_log::{debug, error, warn};
3-
use bevy_math::{Rect, Vec2};
3+
use bevy_math::{Rect, UVec2, Vec2};
44
use bevy_render::{
55
render_resource::{Extent3d, TextureDimension, TextureFormat},
66
texture::{Image, TextureFormatPixelInfo},
@@ -38,6 +38,8 @@ pub struct TextureAtlasBuilder {
3838
format: TextureFormat,
3939
/// Enable automatic format conversion for textures if they are not in the atlas format.
4040
auto_format_conversion: bool,
41+
/// The amount of padding in pixels to add along the right and bottom edges of the texture rects.
42+
padding: UVec2,
4143
}
4244

4345
impl Default for TextureAtlasBuilder {
@@ -48,6 +50,7 @@ impl Default for TextureAtlasBuilder {
4850
max_size: Vec2::new(2048., 2048.),
4951
format: TextureFormat::Rgba8UnormSrgb,
5052
auto_format_conversion: true,
53+
padding: UVec2::ZERO,
5154
}
5255
}
5356
}
@@ -85,20 +88,29 @@ impl TextureAtlasBuilder {
8588
image_id,
8689
None,
8790
RectToInsert::new(
88-
texture.texture_descriptor.size.width,
89-
texture.texture_descriptor.size.height,
91+
texture.texture_descriptor.size.width + self.padding.x,
92+
texture.texture_descriptor.size.height + self.padding.y,
9093
1,
9194
),
9295
);
9396
}
9497

98+
/// Sets the amount of padding in pixels to add between the textures in the texture atlas.
99+
///
100+
/// The `x` value provide will be added to the right edge, while the `y` value will be added to the bottom edge.
101+
pub fn padding(mut self, padding: UVec2) -> Self {
102+
self.padding = padding;
103+
self
104+
}
105+
95106
fn copy_texture_to_atlas(
96107
atlas_texture: &mut Image,
97108
texture: &Image,
98109
packed_location: &PackedLocation,
110+
padding: UVec2,
99111
) {
100-
let rect_width = packed_location.width() as usize;
101-
let rect_height = packed_location.height() as usize;
112+
let rect_width = (packed_location.width() - padding.x) as usize;
113+
let rect_height = (packed_location.height() - padding.y) as usize;
102114
let rect_x = packed_location.x() as usize;
103115
let rect_y = packed_location.y() as usize;
104116
let atlas_width = atlas_texture.texture_descriptor.size.width as usize;
@@ -121,13 +133,18 @@ impl TextureAtlasBuilder {
121133
packed_location: &PackedLocation,
122134
) {
123135
if self.format == texture.texture_descriptor.format {
124-
Self::copy_texture_to_atlas(atlas_texture, texture, packed_location);
136+
Self::copy_texture_to_atlas(atlas_texture, texture, packed_location, self.padding);
125137
} else if let Some(converted_texture) = texture.convert(self.format) {
126138
debug!(
127139
"Converting texture from '{:?}' to '{:?}'",
128140
texture.texture_descriptor.format, self.format
129141
);
130-
Self::copy_texture_to_atlas(atlas_texture, &converted_texture, packed_location);
142+
Self::copy_texture_to_atlas(
143+
atlas_texture,
144+
&converted_texture,
145+
packed_location,
146+
self.padding,
147+
);
131148
} else {
132149
error!(
133150
"Error converting texture from '{:?}' to '{:?}', ignoring",
@@ -213,8 +230,8 @@ impl TextureAtlasBuilder {
213230
let min = Vec2::new(packed_location.x() as f32, packed_location.y() as f32);
214231
let max = min
215232
+ Vec2::new(
216-
packed_location.width() as f32,
217-
packed_location.height() as f32,
233+
(packed_location.width() - self.padding.x) as f32,
234+
(packed_location.height() - self.padding.y) as f32,
218235
);
219236
texture_ids.insert(*image_id, texture_rects.len());
220237
texture_rects.push(Rect { min, max });

0 commit comments

Comments
 (0)