Skip to content

Commit

Permalink
Define ImageSamplerDescriptor that mirrors wgpu::SamplerDescriptor
Browse files Browse the repository at this point in the history
  • Loading branch information
Kanabenki committed Oct 21, 2023
1 parent 6f27e0e commit 200a44f
Showing 1 changed file with 206 additions and 0 deletions.
206 changes: 206 additions & 0 deletions crates/bevy_render/src/texture/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,212 @@ 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 Default for Image {
/// default is a 1x1x1 all '1.0' texture
fn default() -> Self {
Expand Down

0 comments on commit 200a44f

Please sign in to comment.