mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 20:53:53 +00:00
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>
This commit is contained in:
parent
73447b6d72
commit
e663d45e94
1 changed files with 26 additions and 9 deletions
|
@ -1,6 +1,6 @@
|
||||||
use bevy_asset::{AssetId, Assets};
|
use bevy_asset::{AssetId, Assets};
|
||||||
use bevy_log::{debug, error, warn};
|
use bevy_log::{debug, error, warn};
|
||||||
use bevy_math::{Rect, Vec2};
|
use bevy_math::{Rect, UVec2, Vec2};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
render_resource::{Extent3d, TextureDimension, TextureFormat},
|
render_resource::{Extent3d, TextureDimension, TextureFormat},
|
||||||
texture::{Image, TextureFormatPixelInfo},
|
texture::{Image, TextureFormatPixelInfo},
|
||||||
|
@ -38,6 +38,8 @@ pub struct TextureAtlasBuilder {
|
||||||
format: TextureFormat,
|
format: TextureFormat,
|
||||||
/// Enable automatic format conversion for textures if they are not in the atlas format.
|
/// Enable automatic format conversion for textures if they are not in the atlas format.
|
||||||
auto_format_conversion: bool,
|
auto_format_conversion: bool,
|
||||||
|
/// The amount of padding in pixels to add along the right and bottom edges of the texture rects.
|
||||||
|
padding: UVec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TextureAtlasBuilder {
|
impl Default for TextureAtlasBuilder {
|
||||||
|
@ -48,6 +50,7 @@ impl Default for TextureAtlasBuilder {
|
||||||
max_size: Vec2::new(2048., 2048.),
|
max_size: Vec2::new(2048., 2048.),
|
||||||
format: TextureFormat::Rgba8UnormSrgb,
|
format: TextureFormat::Rgba8UnormSrgb,
|
||||||
auto_format_conversion: true,
|
auto_format_conversion: true,
|
||||||
|
padding: UVec2::ZERO,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,20 +88,29 @@ impl TextureAtlasBuilder {
|
||||||
image_id,
|
image_id,
|
||||||
None,
|
None,
|
||||||
RectToInsert::new(
|
RectToInsert::new(
|
||||||
texture.texture_descriptor.size.width,
|
texture.texture_descriptor.size.width + self.padding.x,
|
||||||
texture.texture_descriptor.size.height,
|
texture.texture_descriptor.size.height + self.padding.y,
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the amount of padding in pixels to add between the textures in the texture atlas.
|
||||||
|
///
|
||||||
|
/// The `x` value provide will be added to the right edge, while the `y` value will be added to the bottom edge.
|
||||||
|
pub fn padding(mut self, padding: UVec2) -> Self {
|
||||||
|
self.padding = padding;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn copy_texture_to_atlas(
|
fn copy_texture_to_atlas(
|
||||||
atlas_texture: &mut Image,
|
atlas_texture: &mut Image,
|
||||||
texture: &Image,
|
texture: &Image,
|
||||||
packed_location: &PackedLocation,
|
packed_location: &PackedLocation,
|
||||||
|
padding: UVec2,
|
||||||
) {
|
) {
|
||||||
let rect_width = packed_location.width() as usize;
|
let rect_width = (packed_location.width() - padding.x) as usize;
|
||||||
let rect_height = packed_location.height() as usize;
|
let rect_height = (packed_location.height() - padding.y) as usize;
|
||||||
let rect_x = packed_location.x() as usize;
|
let rect_x = packed_location.x() as usize;
|
||||||
let rect_y = packed_location.y() as usize;
|
let rect_y = packed_location.y() as usize;
|
||||||
let atlas_width = atlas_texture.texture_descriptor.size.width as usize;
|
let atlas_width = atlas_texture.texture_descriptor.size.width as usize;
|
||||||
|
@ -121,13 +133,18 @@ impl TextureAtlasBuilder {
|
||||||
packed_location: &PackedLocation,
|
packed_location: &PackedLocation,
|
||||||
) {
|
) {
|
||||||
if self.format == texture.texture_descriptor.format {
|
if self.format == texture.texture_descriptor.format {
|
||||||
Self::copy_texture_to_atlas(atlas_texture, texture, packed_location);
|
Self::copy_texture_to_atlas(atlas_texture, texture, packed_location, self.padding);
|
||||||
} else if let Some(converted_texture) = texture.convert(self.format) {
|
} else if let Some(converted_texture) = texture.convert(self.format) {
|
||||||
debug!(
|
debug!(
|
||||||
"Converting texture from '{:?}' to '{:?}'",
|
"Converting texture from '{:?}' to '{:?}'",
|
||||||
texture.texture_descriptor.format, self.format
|
texture.texture_descriptor.format, self.format
|
||||||
);
|
);
|
||||||
Self::copy_texture_to_atlas(atlas_texture, &converted_texture, packed_location);
|
Self::copy_texture_to_atlas(
|
||||||
|
atlas_texture,
|
||||||
|
&converted_texture,
|
||||||
|
packed_location,
|
||||||
|
self.padding,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
error!(
|
error!(
|
||||||
"Error converting texture from '{:?}' to '{:?}', ignoring",
|
"Error converting texture from '{:?}' to '{:?}', ignoring",
|
||||||
|
@ -213,8 +230,8 @@ impl TextureAtlasBuilder {
|
||||||
let min = Vec2::new(packed_location.x() as f32, packed_location.y() as f32);
|
let min = Vec2::new(packed_location.x() as f32, packed_location.y() as f32);
|
||||||
let max = min
|
let max = min
|
||||||
+ Vec2::new(
|
+ Vec2::new(
|
||||||
packed_location.width() as f32,
|
(packed_location.width() - self.padding.x) as f32,
|
||||||
packed_location.height() as f32,
|
(packed_location.height() - self.padding.y) as f32,
|
||||||
);
|
);
|
||||||
texture_ids.insert(*image_id, texture_rects.len());
|
texture_ids.insert(*image_id, texture_rects.len());
|
||||||
texture_rects.push(Rect { min, max });
|
texture_rects.push(Rect { min, max });
|
||||||
|
|
Loading…
Reference in a new issue