bevy_render/texture/
mod.rs1mod fallback_image;
2mod gpu_image;
3mod texture_attachment;
4mod texture_cache;
5
6pub use crate::render_resource::DefaultImageSampler;
7#[cfg(feature = "basis-universal")]
8use bevy_image::CompressedImageSaver;
9#[cfg(feature = "hdr")]
10use bevy_image::HdrTextureLoader;
11use bevy_image::{CompressedImageFormats, Image, ImageLoader, ImageSamplerDescriptor};
12pub use fallback_image::*;
13pub use gpu_image::*;
14pub use texture_attachment::*;
15pub use texture_cache::*;
16
17use crate::{
18 render_asset::RenderAssetPlugin, renderer::RenderDevice, Render, RenderApp, RenderSet,
19};
20use bevy_app::{App, Plugin};
21use bevy_asset::{AssetApp, Assets, Handle};
22use bevy_ecs::prelude::*;
23
24pub const TRANSPARENT_IMAGE_HANDLE: Handle<Image> =
30 Handle::weak_from_u128(154728948001857810431816125397303024160);
31
32pub struct ImagePlugin {
35 pub default_sampler: ImageSamplerDescriptor,
37}
38
39impl Default for ImagePlugin {
40 fn default() -> Self {
41 ImagePlugin::default_linear()
42 }
43}
44
45impl ImagePlugin {
46 pub fn default_linear() -> ImagePlugin {
48 ImagePlugin {
49 default_sampler: ImageSamplerDescriptor::linear(),
50 }
51 }
52
53 pub fn default_nearest() -> ImagePlugin {
55 ImagePlugin {
56 default_sampler: ImageSamplerDescriptor::nearest(),
57 }
58 }
59}
60
61impl Plugin for ImagePlugin {
62 fn build(&self, app: &mut App) {
63 #[cfg(feature = "exr")]
64 {
65 app.init_asset_loader::<bevy_image::ExrTextureLoader>();
66 }
67
68 #[cfg(feature = "hdr")]
69 {
70 app.init_asset_loader::<HdrTextureLoader>();
71 }
72
73 app.add_plugins(RenderAssetPlugin::<GpuImage>::default())
74 .register_type::<Image>()
75 .init_asset::<Image>()
76 .register_asset_reflect::<Image>();
77
78 let mut image_assets = app.world_mut().resource_mut::<Assets<Image>>();
79
80 image_assets.insert(&Handle::default(), Image::default());
81 image_assets.insert(&TRANSPARENT_IMAGE_HANDLE, Image::transparent());
82
83 #[cfg(feature = "basis-universal")]
84 if let Some(processor) = app
85 .world()
86 .get_resource::<bevy_asset::processor::AssetProcessor>()
87 {
88 processor.register_processor::<bevy_asset::processor::LoadTransformAndSave<
89 ImageLoader,
90 bevy_asset::transformer::IdentityAssetTransformer<Image>,
91 CompressedImageSaver,
92 >>(CompressedImageSaver.into());
93 processor.set_default_processor::<bevy_asset::processor::LoadTransformAndSave<
94 ImageLoader,
95 bevy_asset::transformer::IdentityAssetTransformer<Image>,
96 CompressedImageSaver,
97 >>("png");
98 }
99
100 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
101 render_app.init_resource::<TextureCache>().add_systems(
102 Render,
103 update_texture_cache_system.in_set(RenderSet::Cleanup),
104 );
105 }
106
107 if !ImageLoader::SUPPORTED_FILE_EXTENSIONS.is_empty() {
108 app.preregister_asset_loader::<ImageLoader>(ImageLoader::SUPPORTED_FILE_EXTENSIONS);
109 }
110 }
111
112 fn finish(&self, app: &mut App) {
113 if !ImageLoader::SUPPORTED_FORMATS.is_empty() {
114 let supported_compressed_formats = match app.world().get_resource::<RenderDevice>() {
115 Some(render_device) => {
116 CompressedImageFormats::from_features(render_device.features())
117 }
118 None => CompressedImageFormats::NONE,
119 };
120 app.register_asset_loader(ImageLoader::new(supported_compressed_formats));
121 }
122
123 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
124 let default_sampler = {
125 let device = render_app.world().resource::<RenderDevice>();
126 device.create_sampler(&self.default_sampler.as_wgpu())
127 };
128 render_app
129 .insert_resource(DefaultImageSampler(default_sampler))
130 .init_resource::<FallbackImage>()
131 .init_resource::<FallbackImageZero>()
132 .init_resource::<FallbackImageCubemap>()
133 .init_resource::<FallbackImageFormatMsaaCache>();
134 }
135 }
136}