Add ImageSamplerDescriptor
as an image loader setting (#9982)
Closes #9946 # Objective Add a new type mirroring `wgpu::SamplerDescriptor` for `ImageLoaderSettings` to control how a loaded image should be sampled. Fix issues with texture sampler descriptors not being set when loading gltf texture from URI. ## Solution Add a new `ImageSamplerDescriptor` and its affiliated types that mirrors `wgpu::SamplerDescriptor`, use it in the image loader settings. --- ## Changelog ### Added - Added new types `ImageSamplerDescriptor`, `ImageAddressMode`, `ImageFilterMode`, `ImageCompareFunction` and `ImageSamplerBorderColor` that mirrors the corresponding wgpu types. - `ImageLoaderSettings` now carries an `ImageSamplerDescriptor` field that will be used to determine how the loaded image is sampled, and will be serialized as part of the image assets `.meta` files. ### Changed - `Image::from_buffer` now takes the sampler descriptor to use as an additional parameter. ### Fixed - Sampler descriptors are set for gltf textures loaded from URI.
This commit is contained in:
parent
af37ab51ec
commit
756fb069b1
@ -346,10 +346,7 @@ pub fn get_lut_bind_group_layout_entries(bindings: [u32; 2]) -> [BindGroupLayout
|
||||
// allow(dead_code) so it doesn't complain when the tonemapping_luts feature is disabled
|
||||
#[allow(dead_code)]
|
||||
fn setup_tonemapping_lut_image(bytes: &[u8], image_type: ImageType) -> Image {
|
||||
let mut image =
|
||||
Image::from_buffer(bytes, image_type, CompressedImageFormats::NONE, false).unwrap();
|
||||
|
||||
image.sampler_descriptor = bevy_render::texture::ImageSampler::Descriptor(SamplerDescriptor {
|
||||
let image_sampler = bevy_render::texture::ImageSampler::Descriptor(SamplerDescriptor {
|
||||
label: Some("Tonemapping LUT sampler"),
|
||||
address_mode_u: AddressMode::ClampToEdge,
|
||||
address_mode_v: AddressMode::ClampToEdge,
|
||||
@ -359,8 +356,14 @@ fn setup_tonemapping_lut_image(bytes: &[u8], image_type: ImageType) -> Image {
|
||||
mipmap_filter: FilterMode::Linear,
|
||||
..default()
|
||||
});
|
||||
|
||||
image
|
||||
Image::from_buffer(
|
||||
bytes,
|
||||
image_type,
|
||||
CompressedImageFormats::NONE,
|
||||
false,
|
||||
image_sampler,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn lut_placeholder() -> Image {
|
||||
|
@ -22,9 +22,10 @@ use bevy_render::{
|
||||
},
|
||||
prelude::SpatialBundle,
|
||||
primitives::Aabb,
|
||||
render_resource::{AddressMode, Face, FilterMode, PrimitiveTopology, SamplerDescriptor},
|
||||
render_resource::{Face, PrimitiveTopology},
|
||||
texture::{
|
||||
CompressedImageFormats, Image, ImageLoaderSettings, ImageSampler, ImageType, TextureError,
|
||||
CompressedImageFormats, Image, ImageAddressMode, ImageFilterMode, ImageLoaderSettings,
|
||||
ImageSampler, ImageSamplerDescriptor, ImageType, TextureError,
|
||||
},
|
||||
};
|
||||
use bevy_scene::Scene;
|
||||
@ -256,9 +257,14 @@ async fn load_gltf<'a, 'b, 'c>(
|
||||
) {
|
||||
let handle = match texture {
|
||||
ImageOrPath::Image { label, image } => load_context.add_labeled_asset(label, image),
|
||||
ImageOrPath::Path { path, is_srgb } => {
|
||||
ImageOrPath::Path {
|
||||
path,
|
||||
is_srgb,
|
||||
sampler_descriptor,
|
||||
} => {
|
||||
load_context.load_with_settings(path, move |settings: &mut ImageLoaderSettings| {
|
||||
settings.is_srgb = is_srgb;
|
||||
settings.sampler_descriptor = sampler_descriptor;
|
||||
})
|
||||
}
|
||||
};
|
||||
@ -667,18 +673,19 @@ async fn load_image<'a, 'b>(
|
||||
supported_compressed_formats: CompressedImageFormats,
|
||||
) -> Result<ImageOrPath, GltfError> {
|
||||
let is_srgb = !linear_textures.contains(&gltf_texture.index());
|
||||
let sampler_descriptor = texture_sampler(&gltf_texture);
|
||||
match gltf_texture.source().source() {
|
||||
gltf::image::Source::View { view, mime_type } => {
|
||||
let start = view.offset();
|
||||
let end = view.offset() + view.length();
|
||||
let buffer = &buffer_data[view.buffer().index()][start..end];
|
||||
let mut image = Image::from_buffer(
|
||||
let image = Image::from_buffer(
|
||||
buffer,
|
||||
ImageType::MimeType(mime_type),
|
||||
supported_compressed_formats,
|
||||
is_srgb,
|
||||
ImageSampler::Descriptor(sampler_descriptor.into()),
|
||||
)?;
|
||||
image.sampler_descriptor = ImageSampler::Descriptor(texture_sampler(&gltf_texture));
|
||||
Ok(ImageOrPath::Image {
|
||||
image,
|
||||
label: texture_label(&gltf_texture),
|
||||
@ -698,6 +705,7 @@ async fn load_image<'a, 'b>(
|
||||
mime_type.map(ImageType::MimeType).unwrap_or(image_type),
|
||||
supported_compressed_formats,
|
||||
is_srgb,
|
||||
ImageSampler::Descriptor(sampler_descriptor.into()),
|
||||
)?,
|
||||
label: texture_label(&gltf_texture),
|
||||
})
|
||||
@ -706,6 +714,7 @@ async fn load_image<'a, 'b>(
|
||||
Ok(ImageOrPath::Path {
|
||||
path: image_path,
|
||||
is_srgb,
|
||||
sampler_descriptor,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1110,32 +1119,32 @@ fn skin_label(skin: &gltf::Skin) -> String {
|
||||
}
|
||||
|
||||
/// Extracts the texture sampler data from the glTF texture.
|
||||
fn texture_sampler<'a>(texture: &gltf::Texture) -> SamplerDescriptor<'a> {
|
||||
fn texture_sampler(texture: &gltf::Texture) -> ImageSamplerDescriptor {
|
||||
let gltf_sampler = texture.sampler();
|
||||
|
||||
SamplerDescriptor {
|
||||
ImageSamplerDescriptor {
|
||||
address_mode_u: texture_address_mode(&gltf_sampler.wrap_s()),
|
||||
address_mode_v: texture_address_mode(&gltf_sampler.wrap_t()),
|
||||
|
||||
mag_filter: gltf_sampler
|
||||
.mag_filter()
|
||||
.map(|mf| match mf {
|
||||
MagFilter::Nearest => FilterMode::Nearest,
|
||||
MagFilter::Linear => FilterMode::Linear,
|
||||
MagFilter::Nearest => ImageFilterMode::Nearest,
|
||||
MagFilter::Linear => ImageFilterMode::Linear,
|
||||
})
|
||||
.unwrap_or(SamplerDescriptor::default().mag_filter),
|
||||
.unwrap_or(ImageSamplerDescriptor::default().mag_filter),
|
||||
|
||||
min_filter: gltf_sampler
|
||||
.min_filter()
|
||||
.map(|mf| match mf {
|
||||
MinFilter::Nearest
|
||||
| MinFilter::NearestMipmapNearest
|
||||
| MinFilter::NearestMipmapLinear => FilterMode::Nearest,
|
||||
| MinFilter::NearestMipmapLinear => ImageFilterMode::Nearest,
|
||||
MinFilter::Linear
|
||||
| MinFilter::LinearMipmapNearest
|
||||
| MinFilter::LinearMipmapLinear => FilterMode::Linear,
|
||||
| MinFilter::LinearMipmapLinear => ImageFilterMode::Linear,
|
||||
})
|
||||
.unwrap_or(SamplerDescriptor::default().min_filter),
|
||||
.unwrap_or(ImageSamplerDescriptor::default().min_filter),
|
||||
|
||||
mipmap_filter: gltf_sampler
|
||||
.min_filter()
|
||||
@ -1143,23 +1152,23 @@ fn texture_sampler<'a>(texture: &gltf::Texture) -> SamplerDescriptor<'a> {
|
||||
MinFilter::Nearest
|
||||
| MinFilter::Linear
|
||||
| MinFilter::NearestMipmapNearest
|
||||
| MinFilter::LinearMipmapNearest => FilterMode::Nearest,
|
||||
| MinFilter::LinearMipmapNearest => ImageFilterMode::Nearest,
|
||||
MinFilter::NearestMipmapLinear | MinFilter::LinearMipmapLinear => {
|
||||
FilterMode::Linear
|
||||
ImageFilterMode::Linear
|
||||
}
|
||||
})
|
||||
.unwrap_or(SamplerDescriptor::default().mipmap_filter),
|
||||
.unwrap_or(ImageSamplerDescriptor::default().mipmap_filter),
|
||||
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps the texture address mode form glTF to wgpu.
|
||||
fn texture_address_mode(gltf_address_mode: &gltf::texture::WrappingMode) -> AddressMode {
|
||||
fn texture_address_mode(gltf_address_mode: &gltf::texture::WrappingMode) -> ImageAddressMode {
|
||||
match gltf_address_mode {
|
||||
WrappingMode::ClampToEdge => AddressMode::ClampToEdge,
|
||||
WrappingMode::Repeat => AddressMode::Repeat,
|
||||
WrappingMode::MirroredRepeat => AddressMode::MirrorRepeat,
|
||||
WrappingMode::ClampToEdge => ImageAddressMode::ClampToEdge,
|
||||
WrappingMode::Repeat => ImageAddressMode::Repeat,
|
||||
WrappingMode::MirroredRepeat => ImageAddressMode::MirrorRepeat,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1280,8 +1289,15 @@ fn resolve_node_hierarchy(
|
||||
}
|
||||
|
||||
enum ImageOrPath {
|
||||
Image { image: Image, label: String },
|
||||
Path { path: PathBuf, is_srgb: bool },
|
||||
Image {
|
||||
image: Image,
|
||||
label: String,
|
||||
},
|
||||
Path {
|
||||
path: PathBuf,
|
||||
is_srgb: bool,
|
||||
sampler_descriptor: ImageSamplerDescriptor,
|
||||
},
|
||||
}
|
||||
|
||||
struct DataUri<'a> {
|
||||
|
@ -1,4 +1,7 @@
|
||||
use crate::texture::{Image, ImageFormat, ImageFormatSetting, ImageLoader, ImageLoaderSettings};
|
||||
use crate::texture::{
|
||||
Image, ImageFormat, ImageFormatSetting, ImageLoader, ImageLoaderSettings, ImageSampler,
|
||||
ImageSamplerDescriptor,
|
||||
};
|
||||
use bevy_asset::saver::{AssetSaver, SavedAsset};
|
||||
use futures_lite::{AsyncWriteExt, FutureExt};
|
||||
use thiserror::Error;
|
||||
@ -30,6 +33,10 @@ impl AssetSaver for CompressedImageSaver {
|
||||
compressor_params.set_basis_format(basis_universal::BasisTextureFormat::UASTC4x4);
|
||||
compressor_params.set_generate_mipmaps(true);
|
||||
let is_srgb = image.texture_descriptor.format.is_srgb();
|
||||
let sampler_descriptor = match &image.sampler_descriptor {
|
||||
ImageSampler::Default => ImageSamplerDescriptor::default(),
|
||||
ImageSampler::Descriptor(sampler_descriptor) => sampler_descriptor.clone().into(),
|
||||
};
|
||||
let color_space = if is_srgb {
|
||||
basis_universal::ColorSpace::Srgb
|
||||
} else {
|
||||
@ -55,6 +62,7 @@ impl AssetSaver for CompressedImageSaver {
|
||||
Ok(ImageLoaderSettings {
|
||||
format: ImageFormatSetting::Format(ImageFormat::Basis),
|
||||
is_srgb,
|
||||
sampler_descriptor,
|
||||
})
|
||||
}
|
||||
.boxed()
|
||||
|
@ -168,6 +168,276 @@ impl ImageSampler {
|
||||
#[derive(Resource, Debug, Clone, Deref, DerefMut)]
|
||||
pub struct DefaultImageSampler(pub(crate) Sampler);
|
||||
|
||||
/// How edges should be handled in texture addressing.
|
||||
///
|
||||
/// This type mirrors [`wgpu::AddressMode`].
|
||||
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
||||
pub enum ImageAddressMode {
|
||||
/// Clamp the value to the edge of the texture.
|
||||
///
|
||||
/// -0.25 -> 0.0
|
||||
/// 1.25 -> 1.0
|
||||
#[default]
|
||||
ClampToEdge,
|
||||
/// Repeat the texture in a tiling fashion.
|
||||
///
|
||||
/// -0.25 -> 0.75
|
||||
/// 1.25 -> 0.25
|
||||
Repeat,
|
||||
/// Repeat the texture, mirroring it every repeat.
|
||||
///
|
||||
/// -0.25 -> 0.25
|
||||
/// 1.25 -> 0.75
|
||||
MirrorRepeat,
|
||||
/// Clamp the value to the border of the texture
|
||||
/// Requires the wgpu feature [`wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER`].
|
||||
///
|
||||
/// -0.25 -> border
|
||||
/// 1.25 -> border
|
||||
ClampToBorder,
|
||||
}
|
||||
|
||||
/// Texel mixing mode when sampling between texels.
|
||||
///
|
||||
/// This type mirrors [`wgpu::FilterMode`].
|
||||
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
||||
pub enum ImageFilterMode {
|
||||
/// Nearest neighbor sampling.
|
||||
///
|
||||
/// This creates a pixelated effect when used as a mag filter.
|
||||
#[default]
|
||||
Nearest,
|
||||
/// Linear Interpolation.
|
||||
///
|
||||
/// This makes textures smooth but blurry when used as a mag filter.
|
||||
Linear,
|
||||
}
|
||||
|
||||
/// Comparison function used for depth and stencil operations.
|
||||
///
|
||||
/// This type mirrors [`wgpu::CompareFunction`].
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub enum ImageCompareFunction {
|
||||
/// Function never passes
|
||||
Never,
|
||||
/// Function passes if new value less than existing value
|
||||
Less,
|
||||
/// Function passes if new value is equal to existing value. When using
|
||||
/// this compare function, make sure to mark your Vertex Shader's `@builtin(position)`
|
||||
/// output as `@invariant` to prevent artifacting.
|
||||
Equal,
|
||||
/// Function passes if new value is less than or equal to existing value
|
||||
LessEqual,
|
||||
/// Function passes if new value is greater than existing value
|
||||
Greater,
|
||||
/// Function passes if new value is not equal to existing value. When using
|
||||
/// this compare function, make sure to mark your Vertex Shader's `@builtin(position)`
|
||||
/// output as `@invariant` to prevent artifacting.
|
||||
NotEqual,
|
||||
/// Function passes if new value is greater than or equal to existing value
|
||||
GreaterEqual,
|
||||
/// Function always passes
|
||||
Always,
|
||||
}
|
||||
|
||||
/// Color variation to use when the sampler addressing mode is [`ImageAddressMode::ClampToBorder`].
|
||||
///
|
||||
/// This type mirrors [`wgpu::SamplerBorderColor`].
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub enum ImageSamplerBorderColor {
|
||||
/// RGBA color `[0, 0, 0, 0]`.
|
||||
TransparentBlack,
|
||||
/// RGBA color `[0, 0, 0, 1]`.
|
||||
OpaqueBlack,
|
||||
/// RGBA color `[1, 1, 1, 1]`.
|
||||
OpaqueWhite,
|
||||
/// On the Metal wgpu backend, this is equivalent to [`Self::TransparentBlack`] for
|
||||
/// textures that have an alpha component, and equivalent to [`Self::OpaqueBlack`]
|
||||
/// for textures that do not have an alpha component. On other backends,
|
||||
/// this is equivalent to [`Self::TransparentBlack`]. Requires
|
||||
/// [`wgpu::Features::ADDRESS_MODE_CLAMP_TO_ZERO`]. Not supported on the web.
|
||||
Zero,
|
||||
}
|
||||
|
||||
/// Indicates to an [`ImageLoader`](super::ImageLoader) how an [`Image`] should be sampled.
|
||||
/// As this type is part of the [`ImageLoaderSettings`](super::ImageLoaderSettings),
|
||||
/// it will be serialized to an image asset `.meta` file which might require a migration in case of
|
||||
/// a breaking change.
|
||||
///
|
||||
/// This types mirrors [`wgpu::SamplerDescriptor`], but that might change in future versions.
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub struct ImageSamplerDescriptor {
|
||||
/// How to deal with out of bounds accesses in the u (i.e. x) direction.
|
||||
pub address_mode_u: ImageAddressMode,
|
||||
/// How to deal with out of bounds accesses in the v (i.e. y) direction.
|
||||
pub address_mode_v: ImageAddressMode,
|
||||
/// How to deal with out of bounds accesses in the w (i.e. z) direction.
|
||||
pub address_mode_w: ImageAddressMode,
|
||||
/// How to filter the texture when it needs to be magnified (made larger).
|
||||
pub mag_filter: ImageFilterMode,
|
||||
/// How to filter the texture when it needs to be minified (made smaller).
|
||||
pub min_filter: ImageFilterMode,
|
||||
/// How to filter between mip map levels
|
||||
pub mipmap_filter: ImageFilterMode,
|
||||
/// Minimum level of detail (i.e. mip level) to use.
|
||||
pub lod_min_clamp: f32,
|
||||
/// Maximum level of detail (i.e. mip level) to use.
|
||||
pub lod_max_clamp: f32,
|
||||
/// If this is enabled, this is a comparison sampler using the given comparison function.
|
||||
pub compare: Option<ImageCompareFunction>,
|
||||
/// Must be at least 1. If this is not 1, all filter modes must be linear.
|
||||
pub anisotropy_clamp: u16,
|
||||
/// Border color to use when `address_mode`` is [`ImageAddressMode::ClampToBorder`].
|
||||
pub border_color: Option<ImageSamplerBorderColor>,
|
||||
}
|
||||
|
||||
impl Default for ImageSamplerDescriptor {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
address_mode_u: Default::default(),
|
||||
address_mode_v: Default::default(),
|
||||
address_mode_w: Default::default(),
|
||||
mag_filter: Default::default(),
|
||||
min_filter: Default::default(),
|
||||
mipmap_filter: Default::default(),
|
||||
lod_min_clamp: 0.0,
|
||||
lod_max_clamp: 32.0,
|
||||
compare: None,
|
||||
anisotropy_clamp: 1,
|
||||
border_color: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ImageAddressMode> for wgpu::AddressMode {
|
||||
fn from(value: ImageAddressMode) -> Self {
|
||||
match value {
|
||||
ImageAddressMode::ClampToEdge => wgpu::AddressMode::ClampToEdge,
|
||||
ImageAddressMode::Repeat => wgpu::AddressMode::Repeat,
|
||||
ImageAddressMode::MirrorRepeat => wgpu::AddressMode::MirrorRepeat,
|
||||
ImageAddressMode::ClampToBorder => wgpu::AddressMode::ClampToBorder,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ImageFilterMode> for wgpu::FilterMode {
|
||||
fn from(value: ImageFilterMode) -> Self {
|
||||
match value {
|
||||
ImageFilterMode::Nearest => wgpu::FilterMode::Nearest,
|
||||
ImageFilterMode::Linear => wgpu::FilterMode::Linear,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ImageCompareFunction> for wgpu::CompareFunction {
|
||||
fn from(value: ImageCompareFunction) -> Self {
|
||||
match value {
|
||||
ImageCompareFunction::Never => wgpu::CompareFunction::Never,
|
||||
ImageCompareFunction::Less => wgpu::CompareFunction::Less,
|
||||
ImageCompareFunction::Equal => wgpu::CompareFunction::Equal,
|
||||
ImageCompareFunction::LessEqual => wgpu::CompareFunction::LessEqual,
|
||||
ImageCompareFunction::Greater => wgpu::CompareFunction::Greater,
|
||||
ImageCompareFunction::NotEqual => wgpu::CompareFunction::NotEqual,
|
||||
ImageCompareFunction::GreaterEqual => wgpu::CompareFunction::GreaterEqual,
|
||||
ImageCompareFunction::Always => wgpu::CompareFunction::Always,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ImageSamplerBorderColor> for wgpu::SamplerBorderColor {
|
||||
fn from(value: ImageSamplerBorderColor) -> Self {
|
||||
match value {
|
||||
ImageSamplerBorderColor::TransparentBlack => wgpu::SamplerBorderColor::TransparentBlack,
|
||||
ImageSamplerBorderColor::OpaqueBlack => wgpu::SamplerBorderColor::OpaqueBlack,
|
||||
ImageSamplerBorderColor::OpaqueWhite => wgpu::SamplerBorderColor::OpaqueWhite,
|
||||
ImageSamplerBorderColor::Zero => wgpu::SamplerBorderColor::Zero,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ImageSamplerDescriptor> for wgpu::SamplerDescriptor<'static> {
|
||||
fn from(value: ImageSamplerDescriptor) -> Self {
|
||||
wgpu::SamplerDescriptor {
|
||||
label: None,
|
||||
address_mode_u: value.address_mode_u.into(),
|
||||
address_mode_v: value.address_mode_v.into(),
|
||||
address_mode_w: value.address_mode_w.into(),
|
||||
mag_filter: value.mag_filter.into(),
|
||||
min_filter: value.min_filter.into(),
|
||||
mipmap_filter: value.mipmap_filter.into(),
|
||||
lod_min_clamp: value.lod_min_clamp,
|
||||
lod_max_clamp: value.lod_max_clamp,
|
||||
compare: value.compare.map(Into::into),
|
||||
anisotropy_clamp: value.anisotropy_clamp,
|
||||
border_color: value.border_color.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wgpu::AddressMode> for ImageAddressMode {
|
||||
fn from(value: wgpu::AddressMode) -> Self {
|
||||
match value {
|
||||
wgpu::AddressMode::ClampToEdge => ImageAddressMode::ClampToEdge,
|
||||
wgpu::AddressMode::Repeat => ImageAddressMode::Repeat,
|
||||
wgpu::AddressMode::MirrorRepeat => ImageAddressMode::MirrorRepeat,
|
||||
wgpu::AddressMode::ClampToBorder => ImageAddressMode::ClampToBorder,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wgpu::FilterMode> for ImageFilterMode {
|
||||
fn from(value: wgpu::FilterMode) -> Self {
|
||||
match value {
|
||||
wgpu::FilterMode::Nearest => ImageFilterMode::Nearest,
|
||||
wgpu::FilterMode::Linear => ImageFilterMode::Linear,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wgpu::CompareFunction> for ImageCompareFunction {
|
||||
fn from(value: wgpu::CompareFunction) -> Self {
|
||||
match value {
|
||||
wgpu::CompareFunction::Never => ImageCompareFunction::Never,
|
||||
wgpu::CompareFunction::Less => ImageCompareFunction::Less,
|
||||
wgpu::CompareFunction::Equal => ImageCompareFunction::Equal,
|
||||
wgpu::CompareFunction::LessEqual => ImageCompareFunction::LessEqual,
|
||||
wgpu::CompareFunction::Greater => ImageCompareFunction::Greater,
|
||||
wgpu::CompareFunction::NotEqual => ImageCompareFunction::NotEqual,
|
||||
wgpu::CompareFunction::GreaterEqual => ImageCompareFunction::GreaterEqual,
|
||||
wgpu::CompareFunction::Always => ImageCompareFunction::Always,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wgpu::SamplerBorderColor> for ImageSamplerBorderColor {
|
||||
fn from(value: wgpu::SamplerBorderColor) -> Self {
|
||||
match value {
|
||||
wgpu::SamplerBorderColor::TransparentBlack => ImageSamplerBorderColor::TransparentBlack,
|
||||
wgpu::SamplerBorderColor::OpaqueBlack => ImageSamplerBorderColor::OpaqueBlack,
|
||||
wgpu::SamplerBorderColor::OpaqueWhite => ImageSamplerBorderColor::OpaqueWhite,
|
||||
wgpu::SamplerBorderColor::Zero => ImageSamplerBorderColor::Zero,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<wgpu::SamplerDescriptor<'a>> for ImageSamplerDescriptor {
|
||||
fn from(value: wgpu::SamplerDescriptor) -> Self {
|
||||
ImageSamplerDescriptor {
|
||||
address_mode_u: value.address_mode_u.into(),
|
||||
address_mode_v: value.address_mode_v.into(),
|
||||
address_mode_w: value.address_mode_w.into(),
|
||||
mag_filter: value.mag_filter.into(),
|
||||
min_filter: value.min_filter.into(),
|
||||
mipmap_filter: value.mipmap_filter.into(),
|
||||
lod_min_clamp: value.lod_min_clamp,
|
||||
lod_max_clamp: value.lod_max_clamp,
|
||||
compare: value.compare.map(Into::into),
|
||||
anisotropy_clamp: value.anisotropy_clamp,
|
||||
border_color: value.border_color.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Image {
|
||||
/// default is a 1x1x1 all '1.0' texture
|
||||
fn default() -> Self {
|
||||
@ -365,6 +635,7 @@ impl Image {
|
||||
image_type: ImageType,
|
||||
#[allow(unused_variables)] supported_compressed_formats: CompressedImageFormats,
|
||||
is_srgb: bool,
|
||||
image_sampler: ImageSampler,
|
||||
) -> Result<Image, TextureError> {
|
||||
let format = image_type.to_image_format()?;
|
||||
|
||||
@ -393,7 +664,9 @@ impl Image {
|
||||
reader.set_format(image_crate_format);
|
||||
reader.no_limits();
|
||||
let dyn_img = reader.decode()?;
|
||||
Ok(Self::from_dynamic(dyn_img, is_srgb))
|
||||
let mut img = Self::from_dynamic(dyn_img, is_srgb);
|
||||
img.sampler_descriptor = image_sampler;
|
||||
Ok(img)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use crate::{
|
||||
texture::{Image, ImageFormat, ImageType, TextureError},
|
||||
};
|
||||
|
||||
use super::CompressedImageFormats;
|
||||
use super::{CompressedImageFormats, ImageSampler, ImageSamplerDescriptor};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Loader for images that can be read by the `image` crate.
|
||||
@ -56,6 +56,7 @@ pub enum ImageFormatSetting {
|
||||
pub struct ImageLoaderSettings {
|
||||
pub format: ImageFormatSetting,
|
||||
pub is_srgb: bool,
|
||||
pub sampler_descriptor: ImageSamplerDescriptor,
|
||||
}
|
||||
|
||||
impl Default for ImageLoaderSettings {
|
||||
@ -63,6 +64,7 @@ impl Default for ImageLoaderSettings {
|
||||
Self {
|
||||
format: ImageFormatSetting::default(),
|
||||
is_srgb: true,
|
||||
sampler_descriptor: ImageSamplerDescriptor::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,6 +103,7 @@ impl AssetLoader for ImageLoader {
|
||||
image_type,
|
||||
self.supported_compressed_formats,
|
||||
settings.is_srgb,
|
||||
ImageSampler::Descriptor(settings.sampler_descriptor.into()),
|
||||
)
|
||||
.map_err(|err| FileTextureError {
|
||||
error: err,
|
||||
|
Loading…
Reference in New Issue
Block a user