|
|
|
@ -13,7 +13,11 @@ use bevy_reflect::Reflect;
|
|
|
|
|
use core::hash::Hash;
|
|
|
|
|
use derive_more::derive::{Display, Error, From};
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use wgpu::{Extent3d, TextureDimension, TextureFormat, TextureViewDescriptor};
|
|
|
|
|
use wgpu::{SamplerDescriptor, TextureViewDescriptor};
|
|
|
|
|
use wgpu_types::{
|
|
|
|
|
AddressMode, CompareFunction, Extent3d, Features, FilterMode, SamplerBorderColor,
|
|
|
|
|
TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pub trait BevyDefault {
|
|
|
|
|
fn bevy_default() -> Self;
|
|
|
|
@ -284,7 +288,7 @@ impl ImageFormat {
|
|
|
|
|
pub struct Image {
|
|
|
|
|
pub data: Vec<u8>,
|
|
|
|
|
// TODO: this nesting makes accessing Image metadata verbose. Either flatten out descriptor or add accessors
|
|
|
|
|
pub texture_descriptor: wgpu::TextureDescriptor<'static>,
|
|
|
|
|
pub texture_descriptor: TextureDescriptor<Option<&'static str>, &'static [TextureFormat]>,
|
|
|
|
|
/// The [`ImageSampler`] to use during rendering.
|
|
|
|
|
pub sampler: ImageSampler,
|
|
|
|
|
pub texture_view_descriptor: Option<TextureViewDescriptor<'static>>,
|
|
|
|
@ -338,7 +342,7 @@ impl ImageSampler {
|
|
|
|
|
///
|
|
|
|
|
/// See [`ImageSamplerDescriptor`] for information how to configure this.
|
|
|
|
|
///
|
|
|
|
|
/// This type mirrors [`wgpu::AddressMode`].
|
|
|
|
|
/// This type mirrors [`AddressMode`].
|
|
|
|
|
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
|
|
|
|
pub enum ImageAddressMode {
|
|
|
|
|
/// Clamp the value to the edge of the texture.
|
|
|
|
@ -358,7 +362,7 @@ pub enum ImageAddressMode {
|
|
|
|
|
/// 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`].
|
|
|
|
|
/// Requires the wgpu feature [`Features::ADDRESS_MODE_CLAMP_TO_BORDER`].
|
|
|
|
|
///
|
|
|
|
|
/// -0.25 -> border
|
|
|
|
|
/// 1.25 -> border
|
|
|
|
@ -367,7 +371,7 @@ pub enum ImageAddressMode {
|
|
|
|
|
|
|
|
|
|
/// Texel mixing mode when sampling between texels.
|
|
|
|
|
///
|
|
|
|
|
/// This type mirrors [`wgpu::FilterMode`].
|
|
|
|
|
/// This type mirrors [`FilterMode`].
|
|
|
|
|
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
|
|
|
|
pub enum ImageFilterMode {
|
|
|
|
|
/// Nearest neighbor sampling.
|
|
|
|
@ -383,7 +387,7 @@ pub enum ImageFilterMode {
|
|
|
|
|
|
|
|
|
|
/// Comparison function used for depth and stencil operations.
|
|
|
|
|
///
|
|
|
|
|
/// This type mirrors [`wgpu::CompareFunction`].
|
|
|
|
|
/// This type mirrors [`CompareFunction`].
|
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
|
|
|
|
pub enum ImageCompareFunction {
|
|
|
|
|
/// Function never passes
|
|
|
|
@ -410,7 +414,7 @@ pub enum ImageCompareFunction {
|
|
|
|
|
|
|
|
|
|
/// Color variation to use when the sampler addressing mode is [`ImageAddressMode::ClampToBorder`].
|
|
|
|
|
///
|
|
|
|
|
/// This type mirrors [`wgpu::SamplerBorderColor`].
|
|
|
|
|
/// This type mirrors [`SamplerBorderColor`].
|
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
|
|
|
|
pub enum ImageSamplerBorderColor {
|
|
|
|
|
/// RGBA color `[0, 0, 0, 0]`.
|
|
|
|
@ -423,7 +427,7 @@ pub enum ImageSamplerBorderColor {
|
|
|
|
|
/// 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.
|
|
|
|
|
/// [`Features::ADDRESS_MODE_CLAMP_TO_ZERO`]. Not supported on the web.
|
|
|
|
|
Zero,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -433,7 +437,7 @@ pub enum ImageSamplerBorderColor {
|
|
|
|
|
/// 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.
|
|
|
|
|
/// This types mirrors [`SamplerDescriptor`], but that might change in future versions.
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
|
|
|
pub struct ImageSamplerDescriptor {
|
|
|
|
|
pub label: Option<String>,
|
|
|
|
@ -503,8 +507,8 @@ impl ImageSamplerDescriptor {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn as_wgpu(&self) -> wgpu::SamplerDescriptor {
|
|
|
|
|
wgpu::SamplerDescriptor {
|
|
|
|
|
pub fn as_wgpu(&self) -> SamplerDescriptor {
|
|
|
|
|
SamplerDescriptor {
|
|
|
|
|
label: self.label.as_deref(),
|
|
|
|
|
address_mode_u: self.address_mode_u.into(),
|
|
|
|
|
address_mode_v: self.address_mode_v.into(),
|
|
|
|
@ -521,100 +525,100 @@ impl ImageSamplerDescriptor {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<ImageAddressMode> for wgpu::AddressMode {
|
|
|
|
|
impl From<ImageAddressMode> for 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,
|
|
|
|
|
ImageAddressMode::ClampToEdge => AddressMode::ClampToEdge,
|
|
|
|
|
ImageAddressMode::Repeat => AddressMode::Repeat,
|
|
|
|
|
ImageAddressMode::MirrorRepeat => AddressMode::MirrorRepeat,
|
|
|
|
|
ImageAddressMode::ClampToBorder => AddressMode::ClampToBorder,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<ImageFilterMode> for wgpu::FilterMode {
|
|
|
|
|
impl From<ImageFilterMode> for FilterMode {
|
|
|
|
|
fn from(value: ImageFilterMode) -> Self {
|
|
|
|
|
match value {
|
|
|
|
|
ImageFilterMode::Nearest => wgpu::FilterMode::Nearest,
|
|
|
|
|
ImageFilterMode::Linear => wgpu::FilterMode::Linear,
|
|
|
|
|
ImageFilterMode::Nearest => FilterMode::Nearest,
|
|
|
|
|
ImageFilterMode::Linear => FilterMode::Linear,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<ImageCompareFunction> for wgpu::CompareFunction {
|
|
|
|
|
impl From<ImageCompareFunction> for 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,
|
|
|
|
|
ImageCompareFunction::Never => CompareFunction::Never,
|
|
|
|
|
ImageCompareFunction::Less => CompareFunction::Less,
|
|
|
|
|
ImageCompareFunction::Equal => CompareFunction::Equal,
|
|
|
|
|
ImageCompareFunction::LessEqual => CompareFunction::LessEqual,
|
|
|
|
|
ImageCompareFunction::Greater => CompareFunction::Greater,
|
|
|
|
|
ImageCompareFunction::NotEqual => CompareFunction::NotEqual,
|
|
|
|
|
ImageCompareFunction::GreaterEqual => CompareFunction::GreaterEqual,
|
|
|
|
|
ImageCompareFunction::Always => CompareFunction::Always,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<ImageSamplerBorderColor> for wgpu::SamplerBorderColor {
|
|
|
|
|
impl From<ImageSamplerBorderColor> for 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,
|
|
|
|
|
ImageSamplerBorderColor::TransparentBlack => SamplerBorderColor::TransparentBlack,
|
|
|
|
|
ImageSamplerBorderColor::OpaqueBlack => SamplerBorderColor::OpaqueBlack,
|
|
|
|
|
ImageSamplerBorderColor::OpaqueWhite => SamplerBorderColor::OpaqueWhite,
|
|
|
|
|
ImageSamplerBorderColor::Zero => SamplerBorderColor::Zero,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<wgpu::AddressMode> for ImageAddressMode {
|
|
|
|
|
fn from(value: wgpu::AddressMode) -> Self {
|
|
|
|
|
impl From<AddressMode> for ImageAddressMode {
|
|
|
|
|
fn from(value: AddressMode) -> Self {
|
|
|
|
|
match value {
|
|
|
|
|
wgpu::AddressMode::ClampToEdge => ImageAddressMode::ClampToEdge,
|
|
|
|
|
wgpu::AddressMode::Repeat => ImageAddressMode::Repeat,
|
|
|
|
|
wgpu::AddressMode::MirrorRepeat => ImageAddressMode::MirrorRepeat,
|
|
|
|
|
wgpu::AddressMode::ClampToBorder => ImageAddressMode::ClampToBorder,
|
|
|
|
|
AddressMode::ClampToEdge => ImageAddressMode::ClampToEdge,
|
|
|
|
|
AddressMode::Repeat => ImageAddressMode::Repeat,
|
|
|
|
|
AddressMode::MirrorRepeat => ImageAddressMode::MirrorRepeat,
|
|
|
|
|
AddressMode::ClampToBorder => ImageAddressMode::ClampToBorder,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<wgpu::FilterMode> for ImageFilterMode {
|
|
|
|
|
fn from(value: wgpu::FilterMode) -> Self {
|
|
|
|
|
impl From<FilterMode> for ImageFilterMode {
|
|
|
|
|
fn from(value: FilterMode) -> Self {
|
|
|
|
|
match value {
|
|
|
|
|
wgpu::FilterMode::Nearest => ImageFilterMode::Nearest,
|
|
|
|
|
wgpu::FilterMode::Linear => ImageFilterMode::Linear,
|
|
|
|
|
FilterMode::Nearest => ImageFilterMode::Nearest,
|
|
|
|
|
FilterMode::Linear => ImageFilterMode::Linear,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<wgpu::CompareFunction> for ImageCompareFunction {
|
|
|
|
|
fn from(value: wgpu::CompareFunction) -> Self {
|
|
|
|
|
impl From<CompareFunction> for ImageCompareFunction {
|
|
|
|
|
fn from(value: 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,
|
|
|
|
|
CompareFunction::Never => ImageCompareFunction::Never,
|
|
|
|
|
CompareFunction::Less => ImageCompareFunction::Less,
|
|
|
|
|
CompareFunction::Equal => ImageCompareFunction::Equal,
|
|
|
|
|
CompareFunction::LessEqual => ImageCompareFunction::LessEqual,
|
|
|
|
|
CompareFunction::Greater => ImageCompareFunction::Greater,
|
|
|
|
|
CompareFunction::NotEqual => ImageCompareFunction::NotEqual,
|
|
|
|
|
CompareFunction::GreaterEqual => ImageCompareFunction::GreaterEqual,
|
|
|
|
|
CompareFunction::Always => ImageCompareFunction::Always,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<wgpu::SamplerBorderColor> for ImageSamplerBorderColor {
|
|
|
|
|
fn from(value: wgpu::SamplerBorderColor) -> Self {
|
|
|
|
|
impl From<SamplerBorderColor> for ImageSamplerBorderColor {
|
|
|
|
|
fn from(value: SamplerBorderColor) -> Self {
|
|
|
|
|
match value {
|
|
|
|
|
wgpu::SamplerBorderColor::TransparentBlack => ImageSamplerBorderColor::TransparentBlack,
|
|
|
|
|
wgpu::SamplerBorderColor::OpaqueBlack => ImageSamplerBorderColor::OpaqueBlack,
|
|
|
|
|
wgpu::SamplerBorderColor::OpaqueWhite => ImageSamplerBorderColor::OpaqueWhite,
|
|
|
|
|
wgpu::SamplerBorderColor::Zero => ImageSamplerBorderColor::Zero,
|
|
|
|
|
SamplerBorderColor::TransparentBlack => ImageSamplerBorderColor::TransparentBlack,
|
|
|
|
|
SamplerBorderColor::OpaqueBlack => ImageSamplerBorderColor::OpaqueBlack,
|
|
|
|
|
SamplerBorderColor::OpaqueWhite => ImageSamplerBorderColor::OpaqueWhite,
|
|
|
|
|
SamplerBorderColor::Zero => ImageSamplerBorderColor::Zero,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> From<wgpu::SamplerDescriptor<'a>> for ImageSamplerDescriptor {
|
|
|
|
|
fn from(value: wgpu::SamplerDescriptor) -> Self {
|
|
|
|
|
impl<'a> From<SamplerDescriptor<'a>> for ImageSamplerDescriptor {
|
|
|
|
|
fn from(value: SamplerDescriptor) -> Self {
|
|
|
|
|
ImageSamplerDescriptor {
|
|
|
|
|
label: value.label.map(ToString::to_string),
|
|
|
|
|
address_mode_u: value.address_mode_u.into(),
|
|
|
|
@ -639,7 +643,7 @@ impl Default for Image {
|
|
|
|
|
let data = vec![255; format.pixel_size()];
|
|
|
|
|
Image {
|
|
|
|
|
data,
|
|
|
|
|
texture_descriptor: wgpu::TextureDescriptor {
|
|
|
|
|
texture_descriptor: TextureDescriptor {
|
|
|
|
|
size: Extent3d {
|
|
|
|
|
width: 1,
|
|
|
|
|
height: 1,
|
|
|
|
@ -650,7 +654,7 @@ impl Default for Image {
|
|
|
|
|
label: None,
|
|
|
|
|
mip_level_count: 1,
|
|
|
|
|
sample_count: 1,
|
|
|
|
|
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
|
|
|
|
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
|
|
|
|
|
view_formats: &[],
|
|
|
|
|
},
|
|
|
|
|
sampler: ImageSampler::Default,
|
|
|
|
@ -701,7 +705,7 @@ impl Image {
|
|
|
|
|
let data = vec![255, 255, 255, 0];
|
|
|
|
|
Image {
|
|
|
|
|
data,
|
|
|
|
|
texture_descriptor: wgpu::TextureDescriptor {
|
|
|
|
|
texture_descriptor: TextureDescriptor {
|
|
|
|
|
size: Extent3d {
|
|
|
|
|
width: 1,
|
|
|
|
|
height: 1,
|
|
|
|
@ -712,7 +716,7 @@ impl Image {
|
|
|
|
|
label: None,
|
|
|
|
|
mip_level_count: 1,
|
|
|
|
|
sample_count: 1,
|
|
|
|
|
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
|
|
|
|
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
|
|
|
|
|
view_formats: &[],
|
|
|
|
|
},
|
|
|
|
|
sampler: ImageSampler::Default,
|
|
|
|
@ -921,13 +925,13 @@ impl Image {
|
|
|
|
|
let format_description = self.texture_descriptor.format;
|
|
|
|
|
format_description
|
|
|
|
|
.required_features()
|
|
|
|
|
.contains(wgpu::Features::TEXTURE_COMPRESSION_ASTC)
|
|
|
|
|
.contains(Features::TEXTURE_COMPRESSION_ASTC)
|
|
|
|
|
|| format_description
|
|
|
|
|
.required_features()
|
|
|
|
|
.contains(wgpu::Features::TEXTURE_COMPRESSION_BC)
|
|
|
|
|
.contains(Features::TEXTURE_COMPRESSION_BC)
|
|
|
|
|
|| format_description
|
|
|
|
|
.required_features()
|
|
|
|
|
.contains(wgpu::Features::TEXTURE_COMPRESSION_ETC2)
|
|
|
|
|
.contains(Features::TEXTURE_COMPRESSION_ETC2)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Compute the byte offset where the data of a specific pixel is stored
|
|
|
|
@ -1497,15 +1501,15 @@ bitflags::bitflags! {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CompressedImageFormats {
|
|
|
|
|
pub fn from_features(features: wgpu::Features) -> Self {
|
|
|
|
|
pub fn from_features(features: Features) -> Self {
|
|
|
|
|
let mut supported_compressed_formats = Self::default();
|
|
|
|
|
if features.contains(wgpu::Features::TEXTURE_COMPRESSION_ASTC) {
|
|
|
|
|
if features.contains(Features::TEXTURE_COMPRESSION_ASTC) {
|
|
|
|
|
supported_compressed_formats |= Self::ASTC_LDR;
|
|
|
|
|
}
|
|
|
|
|
if features.contains(wgpu::Features::TEXTURE_COMPRESSION_BC) {
|
|
|
|
|
if features.contains(Features::TEXTURE_COMPRESSION_BC) {
|
|
|
|
|
supported_compressed_formats |= Self::BC;
|
|
|
|
|
}
|
|
|
|
|
if features.contains(wgpu::Features::TEXTURE_COMPRESSION_ETC2) {
|
|
|
|
|
if features.contains(Features::TEXTURE_COMPRESSION_ETC2) {
|
|
|
|
|
supported_compressed_formats |= Self::ETC2;
|
|
|
|
|
}
|
|
|
|
|
supported_compressed_formats
|
|
|
|
|