mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
use TextureFormat for Textures
This commit also inserts debug asserts that texture data roughly respects the format.
This commit is contained in:
parent
b4c185eb0c
commit
4cf0f53eae
9 changed files with 178 additions and 29 deletions
|
@ -35,7 +35,7 @@ impl Node for TextureCopyNode {
|
|||
let texture_descriptor: TextureDescriptor = texture.into();
|
||||
let width = texture.size.x() as usize;
|
||||
let aligned_width = get_aligned(texture.size.x());
|
||||
let format_size = 4; // TODO: this will be incorrect for some formats
|
||||
let format_size = texture.format.pixel_size();
|
||||
let mut aligned_data =
|
||||
vec![0; format_size * aligned_width * texture.size.y() as usize];
|
||||
texture
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::Texture;
|
||||
use super::{Texture, TextureFormat};
|
||||
use anyhow::Result;
|
||||
use bevy_asset::AssetLoader;
|
||||
use bevy_math::Vec2;
|
||||
|
@ -13,10 +13,11 @@ impl AssetLoader<Texture> for PngTextureLoader {
|
|||
let (info, mut reader) = decoder.read_info()?;
|
||||
let mut data = vec![0; info.buffer_size()];
|
||||
reader.next_frame(&mut data)?;
|
||||
Ok(Texture {
|
||||
Ok(Texture::new(
|
||||
Vec2::new(info.width as f32, info.height as f32),
|
||||
data,
|
||||
size: Vec2::new(info.width as f32, info.height as f32),
|
||||
})
|
||||
TextureFormat::Rgba8UnormSrgb,
|
||||
))
|
||||
}
|
||||
fn extensions(&self) -> &[&str] {
|
||||
static EXTENSIONS: &[&str] = &["png"];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{SamplerDescriptor, TextureDescriptor};
|
||||
use super::{SamplerDescriptor, TextureDescriptor, TextureFormat};
|
||||
use crate::renderer::{
|
||||
RenderResource, RenderResourceContext, RenderResourceId, RenderResourceType,
|
||||
};
|
||||
|
@ -11,22 +11,48 @@ use std::collections::HashSet;
|
|||
pub const TEXTURE_ASSET_INDEX: usize = 0;
|
||||
pub const SAMPLER_ASSET_INDEX: usize = 1;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct Texture {
|
||||
pub data: Vec<u8>,
|
||||
pub size: Vec2,
|
||||
pub format: TextureFormat,
|
||||
}
|
||||
|
||||
const FORMAT_SIZE: usize = 4; // TODO: get this from an actual format type
|
||||
impl Default for Texture {
|
||||
fn default() -> Self {
|
||||
Texture {
|
||||
data: Default::default(),
|
||||
size: Default::default(),
|
||||
format: TextureFormat::Rgba8UnormSrgb,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Texture {
|
||||
pub fn new(data: Vec<u8>, size: Vec2) -> Self {
|
||||
Self { data, size }
|
||||
pub fn new(size: Vec2, data: Vec<u8>, format: TextureFormat) -> Self {
|
||||
debug_assert_eq!(
|
||||
size.x() as usize * size.y() as usize * format.pixel_size(),
|
||||
data.len(),
|
||||
"Pixel data, size and format have to match",
|
||||
);
|
||||
Self { data, size, format }
|
||||
}
|
||||
|
||||
pub fn new_fill(size: Vec2, pixel: &[u8]) -> Self {
|
||||
pub fn new_fill(size: Vec2, pixel: &[u8], format: TextureFormat) -> Self {
|
||||
let mut value = Self::default();
|
||||
value.format = format;
|
||||
value.resize(size);
|
||||
|
||||
debug_assert_eq!(
|
||||
pixel.len() % format.pixel_size(),
|
||||
0,
|
||||
"Must not have incomplete pixel data"
|
||||
);
|
||||
debug_assert!(
|
||||
pixel.len() <= value.data.len(),
|
||||
"Fill data must fit within pixel buffer"
|
||||
);
|
||||
|
||||
for current_pixel in value.data.chunks_exact_mut(pixel.len()) {
|
||||
current_pixel.copy_from_slice(&pixel);
|
||||
}
|
||||
|
@ -41,7 +67,7 @@ impl Texture {
|
|||
self.size = size;
|
||||
let width = size.x() as usize;
|
||||
let height = size.y() as usize;
|
||||
self.data.resize(width * height * FORMAT_SIZE, 0);
|
||||
self.data.resize(width * height * self.format.pixel_size(), 0);
|
||||
}
|
||||
|
||||
pub fn texture_resource_system(
|
||||
|
|
|
@ -21,7 +21,7 @@ impl From<&Texture> for TextureDescriptor {
|
|||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: TextureDimension::D2,
|
||||
format: TextureFormat::Rgba8UnormSrgb,
|
||||
format: texture.format,
|
||||
usage: TextureUsage::SAMPLED | TextureUsage::COPY_DST,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,11 @@ pub enum TextureComponentType {
|
|||
Uint,
|
||||
}
|
||||
|
||||
pub struct PixelInfo {
|
||||
pub type_size: usize,
|
||||
pub num_components: usize,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum TextureFormat {
|
||||
// Normal 8 bit formats
|
||||
|
@ -87,6 +92,113 @@ pub enum TextureFormat {
|
|||
Depth24PlusStencil8 = 37,
|
||||
}
|
||||
|
||||
impl TextureFormat {
|
||||
pub fn pixel_info(&self) -> PixelInfo {
|
||||
let type_size = match self {
|
||||
// 8bit
|
||||
TextureFormat::R8Unorm
|
||||
| TextureFormat::R8Snorm
|
||||
| TextureFormat::R8Uint
|
||||
| TextureFormat::R8Sint
|
||||
| TextureFormat::Rg8Unorm
|
||||
| TextureFormat::Rg8Snorm
|
||||
| TextureFormat::Rg8Uint
|
||||
| TextureFormat::Rg8Sint
|
||||
| TextureFormat::Rgba8Unorm
|
||||
| TextureFormat::Rgba8UnormSrgb
|
||||
| TextureFormat::Rgba8Snorm
|
||||
| TextureFormat::Rgba8Uint
|
||||
| TextureFormat::Rgba8Sint
|
||||
| TextureFormat::Bgra8Unorm
|
||||
| TextureFormat::Bgra8UnormSrgb => 1,
|
||||
|
||||
// 16bit
|
||||
TextureFormat::R16Uint
|
||||
| TextureFormat::R16Sint
|
||||
| TextureFormat::R16Float
|
||||
| TextureFormat::Rg16Uint
|
||||
| TextureFormat::Rg16Sint
|
||||
| TextureFormat::Rg16Float
|
||||
| TextureFormat::Rgba16Uint
|
||||
| TextureFormat::Rgba16Sint
|
||||
| TextureFormat::Rgba16Float => 2,
|
||||
|
||||
// 32bit
|
||||
TextureFormat::R32Uint
|
||||
| TextureFormat::R32Sint
|
||||
| TextureFormat::R32Float
|
||||
| TextureFormat::Rg32Uint
|
||||
| TextureFormat::Rg32Sint
|
||||
| TextureFormat::Rg32Float
|
||||
| TextureFormat::Rgba32Uint
|
||||
| TextureFormat::Rgba32Sint
|
||||
| TextureFormat::Rgba32Float
|
||||
| TextureFormat::Depth32Float => 4,
|
||||
|
||||
// special cases
|
||||
TextureFormat::Rgb10a2Unorm => 4,
|
||||
TextureFormat::Rg11b10Float => 4,
|
||||
TextureFormat::Depth24Plus => 3, // FIXME is this correct?
|
||||
TextureFormat::Depth24PlusStencil8 => 4,
|
||||
};
|
||||
|
||||
let components = match self {
|
||||
TextureFormat::R8Unorm
|
||||
| TextureFormat::R8Snorm
|
||||
| TextureFormat::R8Uint
|
||||
| TextureFormat::R8Sint
|
||||
| TextureFormat::R16Uint
|
||||
| TextureFormat::R16Sint
|
||||
| TextureFormat::R16Float
|
||||
| TextureFormat::R32Uint
|
||||
| TextureFormat::R32Sint
|
||||
| TextureFormat::R32Float => 1,
|
||||
|
||||
TextureFormat::Rg8Unorm
|
||||
| TextureFormat::Rg8Snorm
|
||||
| TextureFormat::Rg8Uint
|
||||
| TextureFormat::Rg8Sint
|
||||
| TextureFormat::Rg16Uint
|
||||
| TextureFormat::Rg16Sint
|
||||
| TextureFormat::Rg16Float
|
||||
| TextureFormat::Rg32Uint
|
||||
| TextureFormat::Rg32Sint
|
||||
| TextureFormat::Rg32Float => 2,
|
||||
|
||||
TextureFormat::Rgba8Unorm
|
||||
| TextureFormat::Rgba8UnormSrgb
|
||||
| TextureFormat::Rgba8Snorm
|
||||
| TextureFormat::Rgba8Uint
|
||||
| TextureFormat::Rgba8Sint
|
||||
| TextureFormat::Bgra8Unorm
|
||||
| TextureFormat::Bgra8UnormSrgb
|
||||
| TextureFormat::Rgba16Uint
|
||||
| TextureFormat::Rgba16Sint
|
||||
| TextureFormat::Rgba16Float
|
||||
| TextureFormat::Rgba32Uint
|
||||
| TextureFormat::Rgba32Sint
|
||||
| TextureFormat::Rgba32Float => 4,
|
||||
|
||||
// special cases
|
||||
TextureFormat::Rgb10a2Unorm
|
||||
| TextureFormat::Rg11b10Float
|
||||
| TextureFormat::Depth32Float
|
||||
| TextureFormat::Depth24Plus
|
||||
| TextureFormat::Depth24PlusStencil8 => 1,
|
||||
};
|
||||
|
||||
PixelInfo {
|
||||
type_size,
|
||||
num_components: components,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pixel_size(&self) -> usize {
|
||||
let info = self.pixel_info();
|
||||
info.type_size * info.num_components
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[repr(transparent)]
|
||||
pub struct TextureUsage: u32 {
|
||||
|
|
|
@ -10,7 +10,6 @@ pub struct DynamicTextureAtlasBuilder {
|
|||
pub atlas_allocator: AtlasAllocator,
|
||||
}
|
||||
|
||||
const FORMAT_SIZE: usize = 4; // TODO: get this from an actual format type
|
||||
impl DynamicTextureAtlasBuilder {
|
||||
pub fn new(size: Vec2) -> Self {
|
||||
Self {
|
||||
|
@ -70,12 +69,13 @@ impl DynamicTextureAtlasBuilder {
|
|||
let rect = allocation.rectangle;
|
||||
let atlas_width = atlas_texture.size.x() as usize;
|
||||
let rect_width = rect.width() as usize;
|
||||
let format_size = atlas_texture.format.pixel_size();
|
||||
|
||||
for (texture_y, bound_y) in (rect.min.y..rect.max.y).map(|i| i as usize).enumerate() {
|
||||
let begin = (bound_y * atlas_width + rect.min.x as usize) * FORMAT_SIZE;
|
||||
let end = begin + rect_width * FORMAT_SIZE;
|
||||
let texture_begin = texture_y * rect_width * FORMAT_SIZE;
|
||||
let texture_end = texture_begin + rect_width * FORMAT_SIZE;
|
||||
let begin = (bound_y * atlas_width + rect.min.x as usize) * format_size;
|
||||
let end = begin + rect_width * format_size;
|
||||
let texture_begin = texture_y * rect_width * format_size;
|
||||
let texture_end = texture_begin + rect_width * format_size;
|
||||
atlas_texture.data[begin..end]
|
||||
.copy_from_slice(&texture.data[texture_begin..texture_end]);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{Rect, TextureAtlas};
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use bevy_math::Vec2;
|
||||
use bevy_render::texture::Texture;
|
||||
use bevy_render::texture::{Texture, TextureFormat};
|
||||
use rectangle_pack::{
|
||||
contains_smallest_box, pack_rects, volume_heuristic, GroupedRectsToPlace, PackedLocation,
|
||||
RectToInsert, TargetBin,
|
||||
|
@ -28,7 +28,6 @@ pub enum RectanglePackError {
|
|||
NotEnoughSpace,
|
||||
}
|
||||
|
||||
const FORMAT_SIZE: usize = 4; // TODO: get this from an actual format type
|
||||
impl TextureAtlasBuilder {
|
||||
pub fn new(initial_size: Vec2, max_size: Vec2) -> Self {
|
||||
Self {
|
||||
|
@ -58,12 +57,13 @@ impl TextureAtlasBuilder {
|
|||
let rect_x = packed_location.x() as usize;
|
||||
let rect_y = packed_location.y() as usize;
|
||||
let atlas_width = atlas_texture.size.x() as usize;
|
||||
let format_size = atlas_texture.format.pixel_size();
|
||||
|
||||
for (texture_y, bound_y) in (rect_y..rect_y + rect_height).enumerate() {
|
||||
let begin = (bound_y * atlas_width + rect_x) * FORMAT_SIZE;
|
||||
let end = begin + rect_width * FORMAT_SIZE;
|
||||
let texture_begin = texture_y * rect_width * FORMAT_SIZE;
|
||||
let texture_end = texture_begin + rect_width * FORMAT_SIZE;
|
||||
let begin = (bound_y * atlas_width + rect_x) * format_size;
|
||||
let end = begin + rect_width * format_size;
|
||||
let texture_begin = texture_y * rect_width * format_size;
|
||||
let texture_end = texture_begin + rect_width * format_size;
|
||||
atlas_texture.data[begin..end]
|
||||
.copy_from_slice(&texture.data[texture_begin..texture_end]);
|
||||
}
|
||||
|
@ -93,6 +93,7 @@ impl TextureAtlasBuilder {
|
|||
atlas_texture = Texture::new_fill(
|
||||
Vec2::new(current_width as f32, current_height as f32),
|
||||
&[0, 0, 0, 0],
|
||||
TextureFormat::Rgba8UnormSrgb,
|
||||
);
|
||||
rect_placements = match pack_rects(
|
||||
&self.rects_to_place,
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use ab_glyph::{FontVec, Glyph, InvalidFont, OutlinedGlyph, Point, PxScale, ScaleFont};
|
||||
use bevy_math::Vec2;
|
||||
use bevy_render::{color::Color, texture::Texture};
|
||||
use bevy_render::{
|
||||
color::Color,
|
||||
texture::{Texture, TextureFormat},
|
||||
};
|
||||
|
||||
pub struct Font {
|
||||
pub font: FontVec,
|
||||
|
@ -32,6 +35,7 @@ impl Font {
|
|||
(color.b * 255.0) as u8,
|
||||
];
|
||||
Texture::new(
|
||||
Vec2::new(width as f32, height as f32),
|
||||
alpha
|
||||
.iter()
|
||||
.map(|a| {
|
||||
|
@ -44,7 +48,7 @@ impl Font {
|
|||
})
|
||||
.flatten()
|
||||
.collect::<Vec<u8>>(),
|
||||
Vec2::new(width as f32, height as f32),
|
||||
TextureFormat::Rgba8UnormSrgb,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -96,6 +100,7 @@ impl Font {
|
|||
}
|
||||
|
||||
Texture::new(
|
||||
Vec2::new(width as f32, height as f32),
|
||||
alpha
|
||||
.iter()
|
||||
.map(|a| {
|
||||
|
@ -108,7 +113,7 @@ impl Font {
|
|||
})
|
||||
.flatten()
|
||||
.collect::<Vec<u8>>(),
|
||||
Vec2::new(width as f32, height as f32),
|
||||
TextureFormat::Rgba8UnormSrgb,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use bevy_asset::{Assets, Handle};
|
||||
use bevy_math::Vec2;
|
||||
use bevy_render::texture::Texture;
|
||||
use bevy_render::texture::{Texture, TextureFormat};
|
||||
use bevy_sprite::{DynamicTextureAtlasBuilder, TextureAtlas};
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
@ -16,7 +16,11 @@ impl FontAtlas {
|
|||
texture_atlases: &mut Assets<TextureAtlas>,
|
||||
size: Vec2,
|
||||
) -> FontAtlas {
|
||||
let atlas_texture = textures.add(Texture::new_fill(size, &[0, 0, 0, 0]));
|
||||
let atlas_texture = textures.add(Texture::new_fill(
|
||||
size,
|
||||
&[0, 0, 0, 0],
|
||||
TextureFormat::Rgba8UnormSrgb,
|
||||
));
|
||||
let texture_atlas = TextureAtlas::new_empty(atlas_texture, size);
|
||||
Self {
|
||||
texture_atlas: texture_atlases.add(texture_atlas),
|
||||
|
|
Loading…
Reference in a new issue