Image Sampler Improvements (#10254)
# Objective - Build on the changes in https://github.com/bevyengine/bevy/pull/9982 - Use `ImageSamplerDescriptor` as the "public image sampler descriptor" interface in all places (for consistency) - Make it possible to configure textures to use the "default" sampler (as configured in the `DefaultImageSampler` resource) - Fix a bug introduced in #9982 that prevents configured samplers from being used in Basis, KTX2, and DDS textures --- ## Migration Guide - When using the `Image` API, use `ImageSamplerDescriptor` instead of `wgpu::SamplerDescriptor` - If writing custom wgpu renderer features that work with `Image`, call `&image_sampler.as_wgpu()` to convert to a wgpu descriptor.
This commit is contained in:
parent
bfca4384cc
commit
134750d18e
@ -346,16 +346,18 @@ 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) so it doesn't complain when the tonemapping_luts feature is disabled
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn setup_tonemapping_lut_image(bytes: &[u8], image_type: ImageType) -> Image {
|
fn setup_tonemapping_lut_image(bytes: &[u8], image_type: ImageType) -> Image {
|
||||||
let image_sampler = bevy_render::texture::ImageSampler::Descriptor(SamplerDescriptor {
|
let image_sampler = bevy_render::texture::ImageSampler::Descriptor(
|
||||||
label: Some("Tonemapping LUT sampler"),
|
bevy_render::texture::ImageSamplerDescriptor {
|
||||||
address_mode_u: AddressMode::ClampToEdge,
|
label: Some("Tonemapping LUT sampler".to_string()),
|
||||||
address_mode_v: AddressMode::ClampToEdge,
|
address_mode_u: bevy_render::texture::ImageAddressMode::ClampToEdge,
|
||||||
address_mode_w: AddressMode::ClampToEdge,
|
address_mode_v: bevy_render::texture::ImageAddressMode::ClampToEdge,
|
||||||
mag_filter: FilterMode::Linear,
|
address_mode_w: bevy_render::texture::ImageAddressMode::ClampToEdge,
|
||||||
min_filter: FilterMode::Linear,
|
mag_filter: bevy_render::texture::ImageFilterMode::Linear,
|
||||||
mipmap_filter: FilterMode::Linear,
|
min_filter: bevy_render::texture::ImageFilterMode::Linear,
|
||||||
..default()
|
mipmap_filter: bevy_render::texture::ImageFilterMode::Linear,
|
||||||
});
|
..default()
|
||||||
|
},
|
||||||
|
);
|
||||||
Image::from_buffer(
|
Image::from_buffer(
|
||||||
bytes,
|
bytes,
|
||||||
image_type,
|
image_type,
|
||||||
@ -385,7 +387,7 @@ pub fn lut_placeholder() -> Image {
|
|||||||
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
|
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
|
||||||
view_formats: &[],
|
view_formats: &[],
|
||||||
},
|
},
|
||||||
sampler_descriptor: ImageSampler::Default,
|
sampler: ImageSampler::Default,
|
||||||
texture_view_descriptor: None,
|
texture_view_descriptor: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ async fn load_gltf<'a, 'b, 'c>(
|
|||||||
} => {
|
} => {
|
||||||
load_context.load_with_settings(path, move |settings: &mut ImageLoaderSettings| {
|
load_context.load_with_settings(path, move |settings: &mut ImageLoaderSettings| {
|
||||||
settings.is_srgb = is_srgb;
|
settings.is_srgb = is_srgb;
|
||||||
settings.sampler_descriptor = sampler_descriptor;
|
settings.sampler = ImageSampler::Descriptor(sampler_descriptor.clone());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -684,7 +684,7 @@ async fn load_image<'a, 'b>(
|
|||||||
ImageType::MimeType(mime_type),
|
ImageType::MimeType(mime_type),
|
||||||
supported_compressed_formats,
|
supported_compressed_formats,
|
||||||
is_srgb,
|
is_srgb,
|
||||||
ImageSampler::Descriptor(sampler_descriptor.into()),
|
ImageSampler::Descriptor(sampler_descriptor),
|
||||||
)?;
|
)?;
|
||||||
Ok(ImageOrPath::Image {
|
Ok(ImageOrPath::Image {
|
||||||
image,
|
image,
|
||||||
@ -705,7 +705,7 @@ async fn load_image<'a, 'b>(
|
|||||||
mime_type.map(ImageType::MimeType).unwrap_or(image_type),
|
mime_type.map(ImageType::MimeType).unwrap_or(image_type),
|
||||||
supported_compressed_formats,
|
supported_compressed_formats,
|
||||||
is_srgb,
|
is_srgb,
|
||||||
ImageSampler::Descriptor(sampler_descriptor.into()),
|
ImageSampler::Descriptor(sampler_descriptor),
|
||||||
)?,
|
)?,
|
||||||
label: texture_label(&gltf_texture),
|
label: texture_label(&gltf_texture),
|
||||||
})
|
})
|
||||||
|
@ -267,7 +267,7 @@ pub struct StandardMaterial {
|
|||||||
/// Use the [`parallax_mapping_method`] and [`max_parallax_layer_count`] fields
|
/// Use the [`parallax_mapping_method`] and [`max_parallax_layer_count`] fields
|
||||||
/// to tweak the shader, trading graphical quality for performance.
|
/// to tweak the shader, trading graphical quality for performance.
|
||||||
///
|
///
|
||||||
/// To improve performance, set your `depth_map`'s [`Image::sampler_descriptor`]
|
/// To improve performance, set your `depth_map`'s [`Image::sampler`]
|
||||||
/// filter mode to `FilterMode::Nearest`, as [this paper] indicates, it improves
|
/// filter mode to `FilterMode::Nearest`, as [this paper] indicates, it improves
|
||||||
/// performance a bit.
|
/// performance a bit.
|
||||||
///
|
///
|
||||||
|
@ -361,10 +361,10 @@ impl FromWorld for MeshPipeline {
|
|||||||
let dummy_white_gpu_image = {
|
let dummy_white_gpu_image = {
|
||||||
let image = Image::default();
|
let image = Image::default();
|
||||||
let texture = render_device.create_texture(&image.texture_descriptor);
|
let texture = render_device.create_texture(&image.texture_descriptor);
|
||||||
let sampler = match image.sampler_descriptor {
|
let sampler = match image.sampler {
|
||||||
ImageSampler::Default => (**default_sampler).clone(),
|
ImageSampler::Default => (**default_sampler).clone(),
|
||||||
ImageSampler::Descriptor(ref descriptor) => {
|
ImageSampler::Descriptor(ref descriptor) => {
|
||||||
render_device.create_sampler(descriptor)
|
render_device.create_sampler(&descriptor.as_wgpu())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
use crate::texture::{
|
use crate::texture::{Image, ImageFormat, ImageFormatSetting, ImageLoader, ImageLoaderSettings};
|
||||||
Image, ImageFormat, ImageFormatSetting, ImageLoader, ImageLoaderSettings, ImageSampler,
|
|
||||||
ImageSamplerDescriptor,
|
|
||||||
};
|
|
||||||
use bevy_asset::saver::{AssetSaver, SavedAsset};
|
use bevy_asset::saver::{AssetSaver, SavedAsset};
|
||||||
use futures_lite::{AsyncWriteExt, FutureExt};
|
use futures_lite::{AsyncWriteExt, FutureExt};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
@ -33,10 +30,6 @@ impl AssetSaver for CompressedImageSaver {
|
|||||||
compressor_params.set_basis_format(basis_universal::BasisTextureFormat::UASTC4x4);
|
compressor_params.set_basis_format(basis_universal::BasisTextureFormat::UASTC4x4);
|
||||||
compressor_params.set_generate_mipmaps(true);
|
compressor_params.set_generate_mipmaps(true);
|
||||||
let is_srgb = image.texture_descriptor.format.is_srgb();
|
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 {
|
let color_space = if is_srgb {
|
||||||
basis_universal::ColorSpace::Srgb
|
basis_universal::ColorSpace::Srgb
|
||||||
} else {
|
} else {
|
||||||
@ -62,7 +55,7 @@ impl AssetSaver for CompressedImageSaver {
|
|||||||
Ok(ImageLoaderSettings {
|
Ok(ImageLoaderSettings {
|
||||||
format: ImageFormatSetting::Format(ImageFormat::Basis),
|
format: ImageFormatSetting::Format(ImageFormat::Basis),
|
||||||
is_srgb,
|
is_srgb,
|
||||||
sampler_descriptor,
|
sampler: image.sampler.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
.boxed()
|
.boxed()
|
||||||
|
@ -100,9 +100,11 @@ fn fallback_image_new(
|
|||||||
array_layer_count: Some(extents.depth_or_array_layers),
|
array_layer_count: Some(extents.depth_or_array_layers),
|
||||||
..TextureViewDescriptor::default()
|
..TextureViewDescriptor::default()
|
||||||
});
|
});
|
||||||
let sampler = match image.sampler_descriptor {
|
let sampler = match image.sampler {
|
||||||
ImageSampler::Default => (**default_sampler).clone(),
|
ImageSampler::Default => (**default_sampler).clone(),
|
||||||
ImageSampler::Descriptor(ref descriptor) => render_device.create_sampler(descriptor),
|
ImageSampler::Descriptor(ref descriptor) => {
|
||||||
|
render_device.create_sampler(&descriptor.as_wgpu())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
GpuImage {
|
GpuImage {
|
||||||
texture,
|
texture,
|
||||||
|
@ -108,55 +108,33 @@ pub struct Image {
|
|||||||
// TODO: this nesting makes accessing Image metadata verbose. Either flatten out descriptor or add accessors
|
// TODO: this nesting makes accessing Image metadata verbose. Either flatten out descriptor or add accessors
|
||||||
pub texture_descriptor: wgpu::TextureDescriptor<'static>,
|
pub texture_descriptor: wgpu::TextureDescriptor<'static>,
|
||||||
/// The [`ImageSampler`] to use during rendering.
|
/// The [`ImageSampler`] to use during rendering.
|
||||||
pub sampler_descriptor: ImageSampler,
|
pub sampler: ImageSampler,
|
||||||
pub texture_view_descriptor: Option<wgpu::TextureViewDescriptor<'static>>,
|
pub texture_view_descriptor: Option<wgpu::TextureViewDescriptor<'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used in [`Image`], this determines what image sampler to use when rendering. The default setting,
|
/// Used in [`Image`], this determines what image sampler to use when rendering. The default setting,
|
||||||
/// [`ImageSampler::Default`], will read the sampler from the [`ImagePlugin`](super::ImagePlugin) at setup.
|
/// [`ImageSampler::Default`], will read the sampler from the [`ImagePlugin`](super::ImagePlugin) at setup.
|
||||||
/// Setting this to [`ImageSampler::Descriptor`] will override the global default descriptor for this [`Image`].
|
/// Setting this to [`ImageSampler::Descriptor`] will override the global default descriptor for this [`Image`].
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
pub enum ImageSampler {
|
pub enum ImageSampler {
|
||||||
/// Default image sampler, derived from the [`ImagePlugin`](super::ImagePlugin) setup.
|
/// Default image sampler, derived from the [`ImagePlugin`](super::ImagePlugin) setup.
|
||||||
#[default]
|
#[default]
|
||||||
Default,
|
Default,
|
||||||
/// Custom sampler for this image which will override global default.
|
/// Custom sampler for this image which will override global default.
|
||||||
Descriptor(wgpu::SamplerDescriptor<'static>),
|
Descriptor(ImageSamplerDescriptor),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageSampler {
|
impl ImageSampler {
|
||||||
/// Returns an image sampler with [`Linear`](crate::render_resource::FilterMode::Linear) min and mag filters
|
/// Returns an image sampler with [`ImageFilterMode::Linear`] min and mag filters
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn linear() -> ImageSampler {
|
pub fn linear() -> ImageSampler {
|
||||||
ImageSampler::Descriptor(Self::linear_descriptor())
|
ImageSampler::Descriptor(ImageSamplerDescriptor::linear())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an image sampler with [`Nearest`](crate::render_resource::FilterMode::Nearest) min and mag filters
|
/// Returns an image sampler with [`ImageFilterMode::Nearest`] min and mag filters
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn nearest() -> ImageSampler {
|
pub fn nearest() -> ImageSampler {
|
||||||
ImageSampler::Descriptor(Self::nearest_descriptor())
|
ImageSampler::Descriptor(ImageSamplerDescriptor::nearest())
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a sampler descriptor with [`Linear`](crate::render_resource::FilterMode::Linear) min and mag filters
|
|
||||||
#[inline]
|
|
||||||
pub fn linear_descriptor() -> wgpu::SamplerDescriptor<'static> {
|
|
||||||
wgpu::SamplerDescriptor {
|
|
||||||
mag_filter: wgpu::FilterMode::Linear,
|
|
||||||
min_filter: wgpu::FilterMode::Linear,
|
|
||||||
mipmap_filter: wgpu::FilterMode::Linear,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a sampler descriptor with [`Nearest`](crate::render_resource::FilterMode::Nearest) min and mag filters
|
|
||||||
#[inline]
|
|
||||||
pub fn nearest_descriptor() -> wgpu::SamplerDescriptor<'static> {
|
|
||||||
wgpu::SamplerDescriptor {
|
|
||||||
mag_filter: wgpu::FilterMode::Nearest,
|
|
||||||
min_filter: wgpu::FilterMode::Nearest,
|
|
||||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,8 +243,9 @@ pub enum ImageSamplerBorderColor {
|
|||||||
/// a breaking change.
|
/// a breaking change.
|
||||||
///
|
///
|
||||||
/// This types mirrors [`wgpu::SamplerDescriptor`], but that might change in future versions.
|
/// This types mirrors [`wgpu::SamplerDescriptor`], but that might change in future versions.
|
||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct ImageSamplerDescriptor {
|
pub struct ImageSamplerDescriptor {
|
||||||
|
pub label: Option<String>,
|
||||||
/// How to deal with out of bounds accesses in the u (i.e. x) direction.
|
/// How to deal with out of bounds accesses in the u (i.e. x) direction.
|
||||||
pub address_mode_u: ImageAddressMode,
|
pub address_mode_u: ImageAddressMode,
|
||||||
/// How to deal with out of bounds accesses in the v (i.e. y) direction.
|
/// How to deal with out of bounds accesses in the v (i.e. y) direction.
|
||||||
@ -305,6 +284,48 @@ impl Default for ImageSamplerDescriptor {
|
|||||||
compare: None,
|
compare: None,
|
||||||
anisotropy_clamp: 1,
|
anisotropy_clamp: 1,
|
||||||
border_color: None,
|
border_color: None,
|
||||||
|
label: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ImageSamplerDescriptor {
|
||||||
|
/// Returns a sampler descriptor with [`Linear`](crate::render_resource::FilterMode::Linear) min and mag filters
|
||||||
|
#[inline]
|
||||||
|
pub fn linear() -> ImageSamplerDescriptor {
|
||||||
|
ImageSamplerDescriptor {
|
||||||
|
mag_filter: ImageFilterMode::Linear,
|
||||||
|
min_filter: ImageFilterMode::Linear,
|
||||||
|
mipmap_filter: ImageFilterMode::Linear,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a sampler descriptor with [`Nearest`](crate::render_resource::FilterMode::Nearest) min and mag filters
|
||||||
|
#[inline]
|
||||||
|
pub fn nearest() -> ImageSamplerDescriptor {
|
||||||
|
ImageSamplerDescriptor {
|
||||||
|
mag_filter: ImageFilterMode::Nearest,
|
||||||
|
min_filter: ImageFilterMode::Nearest,
|
||||||
|
mipmap_filter: ImageFilterMode::Nearest,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_wgpu(&self) -> wgpu::SamplerDescriptor {
|
||||||
|
wgpu::SamplerDescriptor {
|
||||||
|
label: self.label.as_deref(),
|
||||||
|
address_mode_u: self.address_mode_u.into(),
|
||||||
|
address_mode_v: self.address_mode_v.into(),
|
||||||
|
address_mode_w: self.address_mode_w.into(),
|
||||||
|
mag_filter: self.mag_filter.into(),
|
||||||
|
min_filter: self.min_filter.into(),
|
||||||
|
mipmap_filter: self.mipmap_filter.into(),
|
||||||
|
lod_min_clamp: self.lod_min_clamp,
|
||||||
|
lod_max_clamp: self.lod_max_clamp,
|
||||||
|
compare: self.compare.map(Into::into),
|
||||||
|
anisotropy_clamp: self.anisotropy_clamp,
|
||||||
|
border_color: self.border_color.map(Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,25 +376,6 @@ impl From<ImageSamplerBorderColor> for wgpu::SamplerBorderColor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
impl From<wgpu::AddressMode> for ImageAddressMode {
|
||||||
fn from(value: wgpu::AddressMode) -> Self {
|
fn from(value: wgpu::AddressMode) -> Self {
|
||||||
match value {
|
match value {
|
||||||
@ -423,6 +425,7 @@ impl From<wgpu::SamplerBorderColor> for ImageSamplerBorderColor {
|
|||||||
impl<'a> From<wgpu::SamplerDescriptor<'a>> for ImageSamplerDescriptor {
|
impl<'a> From<wgpu::SamplerDescriptor<'a>> for ImageSamplerDescriptor {
|
||||||
fn from(value: wgpu::SamplerDescriptor) -> Self {
|
fn from(value: wgpu::SamplerDescriptor) -> Self {
|
||||||
ImageSamplerDescriptor {
|
ImageSamplerDescriptor {
|
||||||
|
label: value.label.map(|l| l.to_string()),
|
||||||
address_mode_u: value.address_mode_u.into(),
|
address_mode_u: value.address_mode_u.into(),
|
||||||
address_mode_v: value.address_mode_v.into(),
|
address_mode_v: value.address_mode_v.into(),
|
||||||
address_mode_w: value.address_mode_w.into(),
|
address_mode_w: value.address_mode_w.into(),
|
||||||
@ -459,7 +462,7 @@ impl Default for Image {
|
|||||||
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
||||||
view_formats: &[],
|
view_formats: &[],
|
||||||
},
|
},
|
||||||
sampler_descriptor: ImageSampler::Default,
|
sampler: ImageSampler::Default,
|
||||||
texture_view_descriptor: None,
|
texture_view_descriptor: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -645,16 +648,16 @@ impl Image {
|
|||||||
// needs to be added, so the image data needs to be converted in those
|
// needs to be added, so the image data needs to be converted in those
|
||||||
// cases.
|
// cases.
|
||||||
|
|
||||||
match format {
|
let mut image = match format {
|
||||||
#[cfg(feature = "basis-universal")]
|
#[cfg(feature = "basis-universal")]
|
||||||
ImageFormat::Basis => {
|
ImageFormat::Basis => {
|
||||||
basis_buffer_to_image(buffer, supported_compressed_formats, is_srgb)
|
basis_buffer_to_image(buffer, supported_compressed_formats, is_srgb)?
|
||||||
}
|
}
|
||||||
#[cfg(feature = "dds")]
|
#[cfg(feature = "dds")]
|
||||||
ImageFormat::Dds => dds_buffer_to_image(buffer, supported_compressed_formats, is_srgb),
|
ImageFormat::Dds => dds_buffer_to_image(buffer, supported_compressed_formats, is_srgb)?,
|
||||||
#[cfg(feature = "ktx2")]
|
#[cfg(feature = "ktx2")]
|
||||||
ImageFormat::Ktx2 => {
|
ImageFormat::Ktx2 => {
|
||||||
ktx2_buffer_to_image(buffer, supported_compressed_formats, is_srgb)
|
ktx2_buffer_to_image(buffer, supported_compressed_formats, is_srgb)?
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let image_crate_format = format
|
let image_crate_format = format
|
||||||
@ -664,11 +667,11 @@ impl Image {
|
|||||||
reader.set_format(image_crate_format);
|
reader.set_format(image_crate_format);
|
||||||
reader.no_limits();
|
reader.no_limits();
|
||||||
let dyn_img = reader.decode()?;
|
let dyn_img = reader.decode()?;
|
||||||
let mut img = Self::from_dynamic(dyn_img, is_srgb);
|
Self::from_dynamic(dyn_img, is_srgb)
|
||||||
img.sampler_descriptor = image_sampler;
|
|
||||||
Ok(img)
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
image.sampler = image_sampler;
|
||||||
|
Ok(image)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the texture format is compressed or uncompressed
|
/// Whether the texture format is compressed or uncompressed
|
||||||
@ -832,9 +835,11 @@ impl RenderAsset for Image {
|
|||||||
image.texture_descriptor.size.width as f32,
|
image.texture_descriptor.size.width as f32,
|
||||||
image.texture_descriptor.size.height as f32,
|
image.texture_descriptor.size.height as f32,
|
||||||
);
|
);
|
||||||
let sampler = match image.sampler_descriptor {
|
let sampler = match image.sampler {
|
||||||
ImageSampler::Default => (***default_sampler).clone(),
|
ImageSampler::Default => (***default_sampler).clone(),
|
||||||
ImageSampler::Descriptor(descriptor) => render_device.create_sampler(&descriptor),
|
ImageSampler::Descriptor(descriptor) => {
|
||||||
|
render_device.create_sampler(&descriptor.as_wgpu())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(GpuImage {
|
Ok(GpuImage {
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
texture::{Image, ImageFormat, ImageType, TextureError},
|
texture::{Image, ImageFormat, ImageType, TextureError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{CompressedImageFormats, ImageSampler, ImageSamplerDescriptor};
|
use super::{CompressedImageFormats, ImageSampler};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Loader for images that can be read by the `image` crate.
|
/// Loader for images that can be read by the `image` crate.
|
||||||
@ -45,18 +45,18 @@ pub(crate) const IMG_FILE_EXTENSIONS: &[&str] = &[
|
|||||||
"ppm",
|
"ppm",
|
||||||
];
|
];
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Default)]
|
#[derive(Serialize, Deserialize, Default, Debug)]
|
||||||
pub enum ImageFormatSetting {
|
pub enum ImageFormatSetting {
|
||||||
#[default]
|
#[default]
|
||||||
FromExtension,
|
FromExtension,
|
||||||
Format(ImageFormat),
|
Format(ImageFormat),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct ImageLoaderSettings {
|
pub struct ImageLoaderSettings {
|
||||||
pub format: ImageFormatSetting,
|
pub format: ImageFormatSetting,
|
||||||
pub is_srgb: bool,
|
pub is_srgb: bool,
|
||||||
pub sampler_descriptor: ImageSamplerDescriptor,
|
pub sampler: ImageSampler,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ImageLoaderSettings {
|
impl Default for ImageLoaderSettings {
|
||||||
@ -64,7 +64,7 @@ impl Default for ImageLoaderSettings {
|
|||||||
Self {
|
Self {
|
||||||
format: ImageFormatSetting::default(),
|
format: ImageFormatSetting::default(),
|
||||||
is_srgb: true,
|
is_srgb: true,
|
||||||
sampler_descriptor: ImageSamplerDescriptor::default(),
|
sampler: ImageSampler::Default,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ impl AssetLoader for ImageLoader {
|
|||||||
image_type,
|
image_type,
|
||||||
self.supported_compressed_formats,
|
self.supported_compressed_formats,
|
||||||
settings.is_srgb,
|
settings.is_srgb,
|
||||||
ImageSampler::Descriptor(settings.sampler_descriptor.into()),
|
settings.sampler.clone(),
|
||||||
)
|
)
|
||||||
.map_err(|err| FileTextureError {
|
.map_err(|err| FileTextureError {
|
||||||
error: err,
|
error: err,
|
||||||
|
@ -45,7 +45,7 @@ use bevy_ecs::prelude::*;
|
|||||||
/// Adds the [`Image`] as an asset and makes sure that they are extracted and prepared for the GPU.
|
/// Adds the [`Image`] as an asset and makes sure that they are extracted and prepared for the GPU.
|
||||||
pub struct ImagePlugin {
|
pub struct ImagePlugin {
|
||||||
/// The default image sampler to use when [`ImageSampler`] is set to `Default`.
|
/// The default image sampler to use when [`ImageSampler`] is set to `Default`.
|
||||||
pub default_sampler: wgpu::SamplerDescriptor<'static>,
|
pub default_sampler: ImageSamplerDescriptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ImagePlugin {
|
impl Default for ImagePlugin {
|
||||||
@ -58,14 +58,14 @@ impl ImagePlugin {
|
|||||||
/// Creates image settings with linear sampling by default.
|
/// Creates image settings with linear sampling by default.
|
||||||
pub fn default_linear() -> ImagePlugin {
|
pub fn default_linear() -> ImagePlugin {
|
||||||
ImagePlugin {
|
ImagePlugin {
|
||||||
default_sampler: ImageSampler::linear_descriptor(),
|
default_sampler: ImageSamplerDescriptor::linear(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates image settings with nearest sampling by default.
|
/// Creates image settings with nearest sampling by default.
|
||||||
pub fn default_nearest() -> ImagePlugin {
|
pub fn default_nearest() -> ImagePlugin {
|
||||||
ImagePlugin {
|
ImagePlugin {
|
||||||
default_sampler: ImageSampler::nearest_descriptor(),
|
default_sampler: ImageSamplerDescriptor::nearest(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ impl Plugin for ImagePlugin {
|
|||||||
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||||
let default_sampler = {
|
let default_sampler = {
|
||||||
let device = render_app.world.resource::<RenderDevice>();
|
let device = render_app.world.resource::<RenderDevice>();
|
||||||
device.create_sampler(&self.default_sampler.clone())
|
device.create_sampler(&self.default_sampler.as_wgpu())
|
||||||
};
|
};
|
||||||
render_app
|
render_app
|
||||||
.insert_resource(DefaultImageSampler(default_sampler))
|
.insert_resource(DefaultImageSampler(default_sampler))
|
||||||
|
@ -295,10 +295,10 @@ impl FromWorld for Mesh2dPipeline {
|
|||||||
let dummy_white_gpu_image = {
|
let dummy_white_gpu_image = {
|
||||||
let image = Image::default();
|
let image = Image::default();
|
||||||
let texture = render_device.create_texture(&image.texture_descriptor);
|
let texture = render_device.create_texture(&image.texture_descriptor);
|
||||||
let sampler = match image.sampler_descriptor {
|
let sampler = match image.sampler {
|
||||||
ImageSampler::Default => (**default_sampler).clone(),
|
ImageSampler::Default => (**default_sampler).clone(),
|
||||||
ImageSampler::Descriptor(ref descriptor) => {
|
ImageSampler::Descriptor(ref descriptor) => {
|
||||||
render_device.create_sampler(descriptor)
|
render_device.create_sampler(&descriptor.as_wgpu())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,10 +91,10 @@ impl FromWorld for SpritePipeline {
|
|||||||
let dummy_white_gpu_image = {
|
let dummy_white_gpu_image = {
|
||||||
let image = Image::default();
|
let image = Image::default();
|
||||||
let texture = render_device.create_texture(&image.texture_descriptor);
|
let texture = render_device.create_texture(&image.texture_descriptor);
|
||||||
let sampler = match image.sampler_descriptor {
|
let sampler = match image.sampler {
|
||||||
ImageSampler::Default => (**default_sampler).clone(),
|
ImageSampler::Default => (**default_sampler).clone(),
|
||||||
ImageSampler::Descriptor(ref descriptor) => {
|
ImageSampler::Descriptor(ref descriptor) => {
|
||||||
render_device.create_sampler(descriptor)
|
render_device.create_sampler(&descriptor.as_wgpu())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ use bevy::{
|
|||||||
pbr::CascadeShadowConfigBuilder,
|
pbr::CascadeShadowConfigBuilder,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
render::{
|
render::{
|
||||||
render_resource::{Extent3d, SamplerDescriptor, TextureDimension, TextureFormat},
|
render_resource::{Extent3d, TextureDimension, TextureFormat},
|
||||||
texture::ImageSampler,
|
texture::{ImageSampler, ImageSamplerDescriptor},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -371,6 +371,6 @@ fn uv_debug_texture() -> Image {
|
|||||||
&texture_data,
|
&texture_data,
|
||||||
TextureFormat::Rgba8UnormSrgb,
|
TextureFormat::Rgba8UnormSrgb,
|
||||||
);
|
);
|
||||||
img.sampler_descriptor = ImageSampler::Descriptor(SamplerDescriptor::default());
|
img.sampler = ImageSampler::Descriptor(ImageSamplerDescriptor::default());
|
||||||
img
|
img
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,8 @@ use bevy::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypePath,
|
reflect::TypePath,
|
||||||
render::{
|
render::{
|
||||||
render_resource::{
|
render_resource::{AsBindGroup, Extent3d, ShaderRef, TextureDimension, TextureFormat},
|
||||||
AsBindGroup, Extent3d, SamplerDescriptor, ShaderRef, TextureDimension, TextureFormat,
|
texture::{ImageSampler, ImageSamplerDescriptor},
|
||||||
},
|
|
||||||
texture::ImageSampler,
|
|
||||||
view::ColorGrading,
|
view::ColorGrading,
|
||||||
},
|
},
|
||||||
utils::HashMap,
|
utils::HashMap,
|
||||||
@ -681,7 +679,7 @@ fn uv_debug_texture() -> Image {
|
|||||||
&texture_data,
|
&texture_data,
|
||||||
TextureFormat::Rgba8UnormSrgb,
|
TextureFormat::Rgba8UnormSrgb,
|
||||||
);
|
);
|
||||||
img.sampler_descriptor = ImageSampler::Descriptor(SamplerDescriptor::default());
|
img.sampler = ImageSampler::Descriptor(ImageSamplerDescriptor::default());
|
||||||
img
|
img
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user