three_d_asset/
texture.rs

1//!
2//! Contain texture asset definitions.
3//!
4
5pub(crate) mod texture2d;
6pub use texture2d::*;
7
8pub(crate) mod texture3d;
9pub use texture3d::*;
10
11pub use crate::prelude::f16;
12use crate::Srgba;
13
14///
15/// Possible modes of interpolation which determines the texture output between texture pixels.
16///
17#[allow(missing_docs)]
18#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20pub enum Interpolation {
21    Nearest,
22    Linear,
23    CubicSpline,
24}
25
26impl Default for Interpolation {
27    fn default() -> Self {
28        Self::Linear
29    }
30}
31
32/// Mipmap settings for a texture.
33#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
34#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
35pub struct Mipmap {
36    /// Specifies what type of interpolation to use between the two closest mipmaps.
37    pub filter: Interpolation,
38    /// Specifies the maximum number of mipmap levels that should be created for the texture.
39    /// If this is 1, no mip maps will be created.
40    pub max_levels: u32,
41    /// Specifies the maximum ratio of anisotropy to be used when creating mipmaps for the texture.
42    /// If this is 1, only isotropic mipmaps will be created.
43    pub max_ratio: u32,
44}
45
46impl Default for Mipmap {
47    fn default() -> Self {
48        Self {
49            filter: Interpolation::Linear,
50            max_levels: u32::MAX,
51            max_ratio: 1,
52        }
53    }
54}
55
56///
57/// Possible wrapping modes for a texture which determines how the texture is applied outside of the
58/// [0..1] uv coordinate range.
59///
60#[allow(missing_docs)]
61#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
62#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
63pub enum Wrapping {
64    Repeat,
65    MirroredRepeat,
66    ClampToEdge,
67}
68
69///
70/// The pixel/texel data for a [Texture2D] or [Texture3D].
71///
72/// If 2D data, the data array should start with the top left texel and then one row at a time.
73/// The indices `(row, column)` into the 2D data would look like
74/// ```notrust
75/// [
76/// (0, 0), (1, 0), .., // First row
77/// (0, 1), (1, 1), .., // Second row
78/// ..
79/// ]
80/// ```
81/// If 3D data, the data array would look like the 2D data, one layer/image at a time.
82/// The indices `(row, column, layer)` into the 3D data would look like
83/// ```notrust
84/// [
85/// (0, 0, 0), (1, 0, 0), .., // First row in first layer
86/// (0, 1, 0), (1, 1, 0), .., // Second row in first layer
87/// ..
88/// (0, 0, 1), (1, 0, 1), .., // First row in second layer
89/// (0, 1, 1), (1, 1, 1), ..,  // Second row in second layer
90/// ..
91/// ]
92/// ```
93///
94#[derive(Clone, PartialEq)]
95#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
96pub enum TextureData {
97    /// One byte in the red channel.
98    RU8(Vec<u8>),
99    /// One byte in the red and green channel.
100    RgU8(Vec<[u8; 2]>),
101    /// One byte in the red, green and blue channel.
102    RgbU8(Vec<[u8; 3]>),
103    /// One byte in the red, green, blue and alpha channel.
104    RgbaU8(Vec<[u8; 4]>),
105
106    /// 16-bit float in the red channel.
107    RF16(Vec<f16>),
108    /// 16-bit float in the red and green channel.
109    RgF16(Vec<[f16; 2]>),
110    /// 16-bit float in the red, green and blue channel.
111    RgbF16(Vec<[f16; 3]>),
112    /// 16-bit float in the red, green, blue and alpha channel.
113    RgbaF16(Vec<[f16; 4]>),
114
115    /// 32-bit float in the red channel.
116    RF32(Vec<f32>),
117    /// 32-bit float in the red and green channel.
118    RgF32(Vec<[f32; 2]>),
119    /// 32-bit float in the red, green and blue channel.
120    RgbF32(Vec<[f32; 3]>),
121    /// 32-bit float in the red, green, blue and alpha channel.
122    RgbaF32(Vec<[f32; 4]>),
123}
124
125impl std::fmt::Debug for TextureData {
126    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127        match self {
128            Self::RU8(values) => write!(f, "R u8 ({:?})", values.len()),
129            Self::RgU8(values) => write!(f, "RG u8 ({:?})", values.len()),
130            Self::RgbU8(values) => write!(f, "RGB u8 ({:?})", values.len()),
131            Self::RgbaU8(values) => write!(f, "RGBA u8 ({:?})", values.len()),
132            Self::RF16(values) => write!(f, "R f16 ({:?})", values.len()),
133            Self::RgF16(values) => write!(f, "RG f16 ({:?})", values.len()),
134            Self::RgbF16(values) => write!(f, "RGB f16 ({:?})", values.len()),
135            Self::RgbaF16(values) => write!(f, "RGBA f16 ({:?})", values.len()),
136            Self::RF32(values) => write!(f, "R f32 ({:?})", values.len()),
137            Self::RgF32(values) => write!(f, "RG f32 ({:?})", values.len()),
138            Self::RgbF32(values) => write!(f, "RGB f32 ({:?})", values.len()),
139            Self::RgbaF32(values) => write!(f, "RGBA f32 ({:?})", values.len()),
140        }
141    }
142}
143
144impl TextureData {
145    ///
146    /// Converts the texture data to linear sRGB color space if the data is either
147    /// [TextureData::RgbU8] (assuming sRGB color space) or [TextureData::RgbaU8] (assuming sRGB color space with an alpha channel).
148    /// Does nothing if the data is any other data type.
149    ///
150    pub fn to_linear_srgb(&mut self) {
151        match self {
152            TextureData::RgbU8(data) => data.iter_mut().for_each(|color| {
153                *color = Srgba::from(Srgba::from(*color).to_linear_srgb()).into();
154            }),
155            TextureData::RgbaU8(data) => data.iter_mut().for_each(|color| {
156                *color = Srgba::from(Srgba::from(*color).to_linear_srgb()).into();
157            }),
158            _ => {}
159        };
160    }
161
162    ///
163    /// Converts the texture data to color [TextureData::RgbU8] if the data is [TextureData::RU8] (assuming gray scale colors).
164    /// Does nothing if the data is any other data type.
165    ///
166    pub fn to_color(&mut self) {
167        match self {
168            TextureData::RU8(data) => {
169                *self =
170                    TextureData::RgbU8(data.iter().map(|color| [*color, *color, *color]).collect())
171            }
172            _ => {}
173        };
174    }
175}