Skip to main content

bevy_pbr/decal/
forward.rs

1use crate::{
2    ExtendedMaterial, Material, MaterialExtension, MaterialExtensionKey, MaterialExtensionPipeline,
3    MaterialPlugin, StandardMaterial,
4};
5use bevy_app::{App, Plugin};
6use bevy_asset::{Asset, Assets, Handle};
7use bevy_ecs::{
8    component::Component, lifecycle::HookContext, resource::Resource, world::DeferredWorld,
9};
10use bevy_math::{Quat, Vec2, Vec3};
11use bevy_mesh::{Mesh, Mesh3d, MeshBuilder, MeshVertexBufferLayoutRef, Meshable};
12use bevy_reflect::{Reflect, TypePath};
13use bevy_render::{
14    render_asset::RenderAssets,
15    render_resource::{
16        AsBindGroup, AsBindGroupShaderType, CompareFunction, RenderPipelineDescriptor, ShaderType,
17        SpecializedMeshPipelineError,
18    },
19    texture::GpuImage,
20    RenderDebugFlags,
21};
22use bevy_shader::load_shader_library;
23use bevy_shape::Rectangle;
24
25/// Plugin to render [`ForwardDecal`]s.
26pub struct ForwardDecalPlugin;
27
28impl Plugin for ForwardDecalPlugin {
29    fn build(&self, app: &mut App) {
30        {
    {
        let mut embedded =
            app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
        let path =
            {
                let crate_name =
                    "bevy_pbr::decal::forward".split(':').next().unwrap();
                ::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
                    "src".as_ref(), "src/decal/forward.rs".as_ref(),
                    "forward.wesl".as_ref())
            };
        let watched_path =
            ::bevy_asset::io::embedded::watched_path("src/decal/forward.rs",
                "forward.wesl");
        embedded.insert_asset(watched_path, &path,
            b"import package::{\n    render::{\n        forward_io::VertexOutput,\n        mesh_functions::get_world_from_local,\n        mesh_view_bindings::view,\n        pbr_functions::calculate_tbn_mikktspace,\n        view_transformations::depth_ndc_to_view_z,\n    },\n    prepass::utils::prepass_depth,\n};\nimport bevy_render::maths::project_onto;\n\n@group(constants::MATERIAL_BIND_GROUP) @binding(200)\nvar<uniform> inv_depth_fade_factor: f32;\n\nstruct ForwardDecalInformation {\n    world_position: vec4<f32>,\n    uv: vec2<f32>,\n    alpha: f32,\n}\n\nfn get_forward_decal_info(in: VertexOutput) -> ForwardDecalInformation {\n    let world_from_local = get_world_from_local(in.instance_index);\n    let scale = (world_from_local * vec4(1.0, 1.0, 1.0, 0.0)).xyz;\n    let scaled_tangent = vec4(in.world_tangent.xyz / scale, in.world_tangent.w);\n\n    let V = normalize(view.world_position - in.world_position.xyz);\n\n    // Transform V from fragment to camera in world space to tangent space.\n    let TBN = calculate_tbn_mikktspace(in.world_normal, scaled_tangent);\n    let T = TBN[0];\n    let B = TBN[1];\n    let N = TBN[2];\n    let Vt = vec3(dot(V, T), dot(V, B), dot(V, N));\n\n    let frag_depth = depth_ndc_to_view_z(in.position.z);\n    let depth_pass_depth = depth_ndc_to_view_z(prepass_depth(in.position, 0u));\n    let diff_depth = frag_depth - depth_pass_depth;\n    let diff_depth_abs = abs(diff_depth);\n\n    // Apply UV parallax\n    let contact_on_decal = project_onto(V * diff_depth, in.world_normal);\n    let normal_depth = length(contact_on_decal);\n    let view_steepness = abs(Vt.z);\n    let delta_uv = normal_depth * Vt.xy * vec2(1.0, -1.0) / view_steepness;\n    let uv = in.uv + delta_uv;\n\n    let world_position = vec4(in.world_position.xyz + V * diff_depth_abs, in.world_position.w);\n    let alpha = saturate(1.0 - (normal_depth * inv_depth_fade_factor));\n\n    return ForwardDecalInformation(world_position, uv, alpha);\n}\n");
    }
};
let handle:
        ::bevy_shader::_macro::bevy_asset::prelude::Handle<::bevy_shader::prelude::Shader> =
    {
        let (path, asset_server) =
            {
                let path =
                    {
                        {
                            let crate_name =
                                "bevy_pbr::decal::forward".split(':').next().unwrap();
                            ::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
                                "src".as_ref(), "src/decal/forward.rs".as_ref(),
                                "forward.wesl".as_ref())
                        }
                    };
                let path =
                    ::bevy_asset::AssetPath::from_path_buf(path).with_source("embedded");
                let asset_server =
                    ::bevy_asset::io::embedded::GetAssetServer::get_asset_server(app);
                (path, asset_server)
            };
        asset_server.load(path)
    };
::core::mem::forget(handle);load_shader_library!(app, "forward.wesl");
31
32        let mesh = app.world_mut().resource_mut::<Assets<Mesh>>().add(
33            Rectangle::from_size(Vec2::ONE)
34                .mesh()
35                .build()
36                .rotated_by(Quat::from_rotation_arc(Vec3::Z, Vec3::Y))
37                .with_generated_tangents()
38                .unwrap(),
39        );
40
41        app.insert_resource(ForwardDecalMesh(mesh));
42
43        app.add_plugins(MaterialPlugin::<ForwardDecalMaterial<StandardMaterial>> {
44            debug_flags: RenderDebugFlags::default(),
45            ..Default::default()
46        });
47    }
48}
49
50/// A decal that renders via a 1x1 quad mesh, smoothly alpha-blending with the underlying
51/// geometry towards the edges.
52///
53/// Because forward decals are meshes, you can use arbitrary materials to control their appearance.
54///
55/// # Usage Notes
56///
57/// * Spawn this component on an entity with a [`crate::MeshMaterial3d`] component holding a [`ForwardDecalMaterial`].
58/// * Any camera rendering a forward decal must have the [`bevy_core_pipeline::prepass::DepthPrepass`] component.
59/// * Looking at forward decals at a steep angle can cause distortion. This can be mitigated by padding your decal's
60///   texture with extra transparent pixels on the edges.
61/// * On Wasm, requires using WebGPU and disabling `Msaa` on your camera.
62#[derive(#[doc =
"**Required Components**: [`Mesh3d`]. \n\n A component's Required Components are inserted whenever it is inserted. Note that this will also insert the required components _of_ the required components, recursively, in depth-first order."]
impl bevy_ecs::component::Component for ForwardDecal where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {
    const STORAGE_TYPE: bevy_ecs::component::StorageType =
        bevy_ecs::component::StorageType::Table;
    type Mutability = bevy_ecs::component::Mutable;
    fn register_required_components(_requiree:
            bevy_ecs::component::ComponentId,
        required_components:
            &mut bevy_ecs::component::RequiredComponentsRegistrator) {
        required_components.register_required::<Mesh3d>(<Mesh3d as
                ::core::default::Default>::default);
    }
    fn on_add()
        -> ::core::option::Option<bevy_ecs::lifecycle::ComponentHook> {
        ::core::option::Option::Some(forward_decal_set_mesh)
    }
    fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
        use bevy_ecs::component::{
            DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
        };
        (&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
    }
    fn relationship_accessor()
        ->
            ::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
        ::core::option::Option::None
    }
}Component, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for ForwardDecal where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert(<bevy_reflect::ReflectFromPtr as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.insert(<bevy_reflect::ReflectFromReflect as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {}
        }
        impl bevy_reflect::Typed for ForwardDecal where  {
            #[inline(never)]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(#[inline(never)] ||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for ForwardDecal where  {
            fn type_path() -> &'static str {
                "bevy_pbr::decal::forward::ForwardDecal"
            }
            fn short_type_path() -> &'static str { "ForwardDecal" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("ForwardDecal")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_pbr::decal::forward".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_pbr::decal::forward")
            }
        }
        impl bevy_reflect::Reflect for ForwardDecal where  {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        #[allow(non_upper_case_globals)]
        const _: () =
            {
                static __INVENTORY: ::inventory::Node =
                    ::inventory::Node {
                        value: &{
                                bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<ForwardDecal
                                        as
                                        bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
                            },
                        next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
                    };
                #[link_section = ".text.startup"]
                unsafe extern "C" fn __ctor() {
                    unsafe {
                        ::inventory::ErasedNode::submit(__INVENTORY.value,
                            &__INVENTORY)
                    }
                }
                #[used]
                #[link_section = ".init_array"]
                static __CTOR: unsafe extern "C" fn() = __ctor;
            };
        impl bevy_reflect::structs::Struct for ForwardDecal where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name { _ => ::core::option::Option::None, }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name { _ => ::core::option::Option::None, }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index { _ => ::core::option::Option::None, }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index { _ => ::core::option::Option::None, }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index { _ => ::core::option::Option::None, }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name { _ => ::core::option::Option::None, }
            }
            fn field_len(&self) -> usize { 0usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                ->
                    ::core::result::Result<bevy_reflect::structs::DynamicStruct,
                    bevy_reflect::ReflectCloneError> {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                ::core::result::Result::Ok(dynamic)
            }
        }
        impl bevy_reflect::PartialReflect for ForwardDecal where  {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Struct(struct_value) =
                        bevy_reflect::PartialReflect::reflect_ref(value) {
                    for (name, value) in
                        bevy_reflect::structs::Struct::iter_fields(struct_value) {
                        if let ::core::option::Option::Some(v) =
                                bevy_reflect::structs::Struct::field_mut(self, name) {
                            bevy_reflect::PartialReflect::try_apply(v, value)?;
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
                                to_kind: bevy_reflect::ReflectKind::Struct,
                            });
                }
                ::core::result::Result::Ok(())
            }
            #[inline]
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Struct
            }
            #[inline]
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Struct(self)
            }
            #[inline]
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Struct(self)
            }
            #[inline]
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Struct(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::structs::struct_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::structs::struct_partial_cmp)(self, value)
            }
            #[inline]
            #[allow(unreachable_code, reason =
            "Ignored fields without a `clone` attribute will early-return with an error")]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(Self {}))
            }
        }
        impl bevy_reflect::FromReflect for ForwardDecal where  {
            fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
                        bevy_reflect::PartialReflect::reflect_ref(reflect) {
                    let __this = Self {};
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect)]
63#[require(Mesh3d)]
64#[component(on_add=forward_decal_set_mesh)]
65pub struct ForwardDecal;
66
67/// Type alias for an extended material with a [`ForwardDecalMaterialExt`] extension.
68///
69/// Make sure to register the [`MaterialPlugin`] for this material in your app setup.
70///
71/// [`StandardMaterial`] comes with out of the box support for forward decals.
72#[expect(type_alias_bounds, reason = "Type alias generics not yet stable")]
73pub type ForwardDecalMaterial<B: Material> = ExtendedMaterial<B, ForwardDecalMaterialExt>;
74
75/// Material extension for a [`ForwardDecal`].
76///
77/// In addition to wrapping your material type with this extension, your shader must use
78/// the `bevy_pbr::decal::forward::get_forward_decal_info` function.
79///
80/// The `FORWARD_DECAL` shader define will be made available to your shader so that you can gate
81/// the forward decal code behind an ifdef.
82#[derive(impl bevy_asset::Asset for ForwardDecalMaterialExt {}
impl bevy_asset::VisitAssetDependencies for ForwardDecalMaterialExt {
    fn visit_dependencies(&self,
        visit: &mut impl ::core::ops::FnMut(bevy_asset::UntypedAssetId)) {}
}Asset, impl bevy_render::render_resource::AsBindGroup for ForwardDecalMaterialExt {
    type Data = ();
    type Param =
        (bevy_ecs::system::lifetimeless::SRes<bevy_render::render_asset::RenderAssets<bevy_render::texture::GpuImage>>,
        bevy_ecs::system::lifetimeless::SRes<bevy_render::texture::FallbackImage>,
        bevy_ecs::system::lifetimeless::SRes<bevy_render::render_asset::RenderAssets<bevy_render::storage::GpuShaderBuffer>>);
    fn label() -> &'static str { "ForwardDecalMaterialExt" }
    fn build_bind_group(&self,
        layout: &bevy_render::render_resource::BindGroupLayout,
        render_device: &bevy_render::renderer::RenderDevice,
        (images, fallback_image, storage_buffers):
            &mut bevy_ecs::system::SystemParamItem<'_, '_, Self::Param>,
        force_no_bindless: bool,
        output: &mut bevy_render::render_resource::BindGroupBuilder)
        ->
            ::core::result::Result<(),
            bevy_render::render_resource::AsBindGroupError> {
        let (uniform_binding_type, uniform_buffer_usages) =
            (bevy_render::render_resource::BufferBindingType::Uniform,
                bevy_render::render_resource::BufferUsages::UNIFORM);
        let binding_impl =
            {
                use bevy_render::render_resource::AsBindGroupShaderType;
                let mut buffer =
                    bevy_render::render_resource::encase::UniformBuffer::new(::std::vec::Vec::new());
                let converted: ForwardDecalMaterialExtUniform =
                    self.as_bind_group_shader_type(&images);
                buffer.write(&converted).unwrap();
                (200u32,
                    bevy_render::render_resource::UnpreparedBindingResource::Buffer(render_device.create_buffer_with_data(&bevy_render::render_resource::BufferInitDescriptor {
                                    label: ::core::option::Option::None,
                                    usage: uniform_buffer_usages,
                                    contents: buffer.as_ref(),
                                })))
            };
        output.binding_resources.push(binding_impl);
        ::core::result::Result::Ok(())
    }
    #[allow(clippy :: unused_unit)]
    fn bind_group_data(&self) -> Self::Data { () }
    fn bind_group_layout_entries(render_device:
            &bevy_render::renderer::RenderDevice, force_no_bindless: bool)
        ->
            ::std::vec::Vec<bevy_render::render_resource::BindGroupLayoutEntry> {
        let actual_bindless_slot_count:
                ::core::option::Option<::core::num::NonZeroU32> =
            ::core::option::Option::None;
        let (uniform_binding_type, uniform_buffer_usages) =
            (bevy_render::render_resource::BufferBindingType::Uniform,
                bevy_render::render_resource::BufferUsages::UNIFORM);
        let mut bind_group_layout_entries = ::std::vec::Vec::new();
        match actual_bindless_slot_count {
            ::core::option::Option::Some(bindless_slot_count) => {
                let bindless_index_table_range =
                    bevy_render::render_resource::BindlessIndex(0)..bevy_render::render_resource::BindlessIndex(201u32);
                let used_resource_types =
                    &[bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::None,
                                bevy_render::render_resource::BindlessResourceType::Buffer];
                bind_group_layout_entries.extend(bevy_render::render_resource::create_bindless_bind_group_layout_entries(bindless_index_table_range.end.0
                                - bindless_index_table_range.start.0,
                            bindless_slot_count.into(),
                            bevy_render::render_resource::BindingNumber(0),
                            used_resource_types).into_iter());
                bind_group_layout_entries.push(bevy_render::render_resource::BindGroupLayoutEntry {
                        binding: 0u32,
                        visibility: bevy_render::render_resource::ShaderStages::FRAGMENT
                                | bevy_render::render_resource::ShaderStages::VERTEX |
                            bevy_render::render_resource::ShaderStages::COMPUTE,
                        ty: bevy_render::render_resource::BindingType::Buffer {
                            ty: uniform_binding_type,
                            has_dynamic_offset: false,
                            min_binding_size: ::core::option::Option::Some(<ForwardDecalMaterialExtUniform
                                        as bevy_render::render_resource::ShaderType>::min_size()),
                        },
                        count: actual_bindless_slot_count,
                    });
                ;
            }
            ::core::option::Option::None => {
                bind_group_layout_entries.push(bevy_render::render_resource::BindGroupLayoutEntry {
                        binding: 200u32,
                        visibility: bevy_render::render_resource::ShaderStages::FRAGMENT
                                | bevy_render::render_resource::ShaderStages::VERTEX |
                            bevy_render::render_resource::ShaderStages::COMPUTE,
                        ty: bevy_render::render_resource::BindingType::Buffer {
                            ty: uniform_binding_type,
                            has_dynamic_offset: false,
                            min_binding_size: ::core::option::Option::Some(<ForwardDecalMaterialExtUniform
                                        as bevy_render::render_resource::ShaderType>::min_size()),
                        },
                        count: ::core::option::Option::None,
                    });
                ;
            }
        };
        bind_group_layout_entries
    }
    fn bindless_descriptor()
        ->
            ::core::option::Option<bevy_render::render_resource::BindlessDescriptor> {
        ::core::option::Option::None
    }
}AsBindGroup, const _: () =
    {
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for ForwardDecalMaterialExt where  {
            fn type_path() -> &'static str {
                "bevy_pbr::decal::forward::ForwardDecalMaterialExt"
            }
            fn short_type_path() -> &'static str { "ForwardDecalMaterialExt" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("ForwardDecalMaterialExt")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_pbr::decal::forward".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_pbr::decal::forward")
            }
        }
    };TypePath, #[automatically_derived]
impl ::core::clone::Clone for ForwardDecalMaterialExt {
    #[inline]
    fn clone(&self) -> Self {
        Self {
            depth_fade_factor: ::core::clone::Clone::clone(&self.depth_fade_factor),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for ForwardDecalMaterialExt {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "ForwardDecalMaterialExt", "depth_fade_factor",
            &&self.depth_fade_factor)
    }
}Debug)]
83#[uniform(200, ForwardDecalMaterialExtUniform)]
84pub struct ForwardDecalMaterialExt {
85    /// Controls the distance threshold for decal blending with surfaces.
86    ///
87    /// This parameter determines how far away a surface can be before the decal no longer blends
88    /// with it and instead renders with full opacity.
89    ///
90    /// Lower values cause the decal to only blend with close surfaces, while higher values allow
91    /// blending with more distant surfaces.
92    ///
93    /// Units are in meters.
94    /// This has no effect if alpha mode is `Opaque`.
95    pub depth_fade_factor: f32,
96}
97
98#[derive(#[automatically_derived]
impl ::core::clone::Clone for ForwardDecalMaterialExtUniform {
    #[inline]
    fn clone(&self) -> Self {
        Self {
            inv_depth_fade_factor: ::core::clone::Clone::clone(&self.inv_depth_fade_factor),
        }
    }
}Clone, #[automatically_derived]
impl ::core::default::Default for ForwardDecalMaterialExtUniform {
    #[inline]
    fn default() -> Self {
        Self { inv_depth_fade_factor: ::core::default::Default::default() }
    }
}Default, impl bevy_render::render_resource::encase::private::ShaderType for
    ForwardDecalMaterialExtUniform where
    f32: bevy_render::render_resource::encase::private::ShaderType {
    type ExtraMetadata =
        bevy_render::render_resource::encase::private::StructMetadata<1usize>;
    const METADATA:
        bevy_render::render_resource::encase::private::Metadata<Self::ExtraMetadata>
        =
        {
            let struct_alignment =
                bevy_render::render_resource::encase::private::AlignmentValue::max([<f32
                                    as
                                    bevy_render::render_resource::encase::private::ShaderType>::METADATA.alignment()]);
            let extra =
                {
                    let mut paddings = [0; 1usize];
                    let mut offsets = [0; 1usize];
                    let mut offset = 0;
                    offset +=
                        <f32 as
                                bevy_render::render_resource::encase::private::ShaderSize>::SHADER_SIZE.get();
                    paddings[0usize] =
                        struct_alignment.padding_needed_for(offset);
                    bevy_render::render_resource::encase::private::StructMetadata {
                        offsets,
                        paddings,
                    }
                };
            let min_size =
                {
                    let mut offset = extra.offsets[1usize - 1];
                    offset +=
                        <f32 as
                                    bevy_render::render_resource::encase::private::ShaderType>::METADATA.min_size().get();
                    bevy_render::render_resource::encase::private::SizeValue::new(struct_alignment.round_up(offset))
                };
            bevy_render::render_resource::encase::private::Metadata {
                alignment: struct_alignment,
                has_uniform_min_alignment: true,
                min_size,
                is_pod: false,
                extra,
            }
        };
    const UNIFORM_COMPAT_ASSERT: fn() =
        ||
            bevy_render::render_resource::encase::private::consume_zsts([<f32
                                as
                                bevy_render::render_resource::encase::private::ShaderType>::UNIFORM_COMPAT_ASSERT(),
                        if let ::core::option::Option::Some(min_alignment) =
                                <f32 as
                                        bevy_render::render_resource::encase::private::ShaderType>::METADATA.uniform_min_alignment()
                            {
                            let offset =
                                <Self as
                                        bevy_render::render_resource::encase::private::ShaderType>::METADATA.offset(0usize);
                            {

                                #[allow(clippy :: equatable_if_let)]
                                if let false = min_alignment.is_aligned(offset) {
                                    {
                                        let mut fmt: ::const_panic::FmtArg =
                                            ::const_panic::FmtArg::DEBUG;
                                        match &[::const_panic::StdWrapper(&match &"offset of field '"
                                                                            {
                                                                            reff =>
                                                                                ::const_panic::__::PanicFmt::PROOF.infer(reff).coerce(reff),
                                                                        }.to_panicvals(fmt.set_display().set_alternate(false))).deref_panic_vals(),
                                                        ::const_panic::StdWrapper(&match &"inv_depth_fade_factor" {
                                                                            reff =>
                                                                                ::const_panic::__::PanicFmt::PROOF.infer(reff).coerce(reff),
                                                                        }.to_panicvals(fmt.set_display().set_alternate(false))).deref_panic_vals(),
                                                        ::const_panic::StdWrapper(&match &"' must be a multiple of "
                                                                            {
                                                                            reff =>
                                                                                ::const_panic::__::PanicFmt::PROOF.infer(reff).coerce(reff),
                                                                        }.to_panicvals(fmt.set_display().set_alternate(false))).deref_panic_vals(),
                                                        ::const_panic::StdWrapper(&match &min_alignment.get() {
                                                                            reff =>
                                                                                ::const_panic::__::PanicFmt::PROOF.infer(reff).coerce(reff),
                                                                        }.to_panicvals(fmt)).deref_panic_vals(),
                                                        ::const_panic::StdWrapper(&match &" (current offset: " {
                                                                            reff =>
                                                                                ::const_panic::__::PanicFmt::PROOF.infer(reff).coerce(reff),
                                                                        }.to_panicvals(fmt.set_display().set_alternate(false))).deref_panic_vals(),
                                                        ::const_panic::StdWrapper(&match &offset {
                                                                            reff =>
                                                                                ::const_panic::__::PanicFmt::PROOF.infer(reff).coerce(reff),
                                                                        }.to_panicvals(fmt)).deref_panic_vals(),
                                                        ::const_panic::StdWrapper(&match &")" {
                                                                            reff =>
                                                                                ::const_panic::__::PanicFmt::PROOF.infer(reff).coerce(reff),
                                                                        }.to_panicvals(fmt.set_display().set_alternate(false))).deref_panic_vals()]
                                            {
                                            args => ::const_panic::concat_panic(args),
                                        }
                                    }
                                }
                            }
                        }, ()]);
    fn size(&self) -> ::core::num::NonZeroU64 {
        let mut offset = Self::METADATA.last_offset();
        offset +=
            bevy_render::render_resource::encase::private::ShaderType::size(&self.inv_depth_fade_factor).get();
        bevy_render::render_resource::encase::private::SizeValue::new(Self::METADATA.alignment().round_up(offset)).0
    }
}
impl bevy_render::render_resource::encase::private::WriteInto for
    ForwardDecalMaterialExtUniform where
    Self: bevy_render::render_resource::encase::private::ShaderType<ExtraMetadata
    = bevy_render::render_resource::encase::private::StructMetadata<1usize>>,
    for<'__> f32: bevy_render::render_resource::encase::private::WriteInto {
    #[inline]
    fn write_into<B: bevy_render::render_resource::encase::private::BufferMut>(&self,
        writer:
            &mut bevy_render::render_resource::encase::private::Writer<B>) {
        bevy_render::render_resource::encase::private::WriteInto::write_into(&self.inv_depth_fade_factor,
            writer);
        bevy_render::render_resource::encase::private::Writer::advance(writer,
            <Self as
                        bevy_render::render_resource::encase::private::ShaderType>::METADATA.padding(0usize)
                as ::core::primitive::usize);
    }
}
impl bevy_render::render_resource::encase::private::ReadFrom for
    ForwardDecalMaterialExtUniform where
    Self: bevy_render::render_resource::encase::private::ShaderType<ExtraMetadata
    = bevy_render::render_resource::encase::private::StructMetadata<1usize>>,
    for<'__> f32: bevy_render::render_resource::encase::private::ReadFrom {
    #[inline]
    fn read_from<B: bevy_render::render_resource::encase::private::BufferRef>(&mut self,
        reader:
            &mut bevy_render::render_resource::encase::private::Reader<B>) {
        bevy_render::render_resource::encase::private::ReadFrom::read_from(&mut self.inv_depth_fade_factor,
            reader);
        bevy_render::render_resource::encase::private::Reader::advance(reader,
            <Self as
                        bevy_render::render_resource::encase::private::ShaderType>::METADATA.padding(0usize)
                as ::core::primitive::usize);
    }
}
impl bevy_render::render_resource::encase::private::CreateFrom for
    ForwardDecalMaterialExtUniform where
    Self: bevy_render::render_resource::encase::private::ShaderType<ExtraMetadata
    = bevy_render::render_resource::encase::private::StructMetadata<1usize>>,
    for<'__> f32: bevy_render::render_resource::encase::private::CreateFrom {
    #[inline]
    fn create_from<B: bevy_render::render_resource::encase::private::BufferRef>(reader:
            &mut bevy_render::render_resource::encase::private::Reader<B>)
        -> Self {
        let inv_depth_fade_factor =
            bevy_render::render_resource::encase::private::CreateFrom::create_from(reader);
        bevy_render::render_resource::encase::private::Reader::advance(reader,
            <Self as
                        bevy_render::render_resource::encase::private::ShaderType>::METADATA.padding(0usize)
                as ::core::primitive::usize);
        {
            let mut uninit_struct =
                ::core::mem::MaybeUninit::<Self>::uninit();
            let ptr =
                ::core::mem::MaybeUninit::as_mut_ptr(&mut uninit_struct);
            let field_ptr = unsafe { &raw mut (*ptr).inv_depth_fade_factor };
            unsafe { field_ptr.write(inv_depth_fade_factor) };
            ;
            unsafe { ::core::mem::MaybeUninit::assume_init(uninit_struct) }
        }
    }
}
impl bevy_render::render_resource::encase::private::ShaderSize for
    ForwardDecalMaterialExtUniform where
    f32: bevy_render::render_resource::encase::private::ShaderSize {}ShaderType)]
99pub struct ForwardDecalMaterialExtUniform {
100    pub inv_depth_fade_factor: f32,
101}
102
103impl AsBindGroupShaderType<ForwardDecalMaterialExtUniform> for ForwardDecalMaterialExt {
104    fn as_bind_group_shader_type(
105        &self,
106        _images: &RenderAssets<GpuImage>,
107    ) -> ForwardDecalMaterialExtUniform {
108        ForwardDecalMaterialExtUniform {
109            inv_depth_fade_factor: 1.0 / self.depth_fade_factor.max(0.001),
110        }
111    }
112}
113
114impl MaterialExtension for ForwardDecalMaterialExt {
115    // Forward decal is incompatible with OIT as it needs to be rendered
116    // even it's occluded by opaque objects.
117    fn enable_oit() -> bool {
118        false
119    }
120
121    // Don't write forward decal's own depth if it is opaque.
122    fn enable_prepass() -> bool {
123        false
124    }
125
126    fn enable_shadows() -> bool {
127        false
128    }
129
130    fn specialize(
131        _pipeline: &MaterialExtensionPipeline,
132        descriptor: &mut RenderPipelineDescriptor,
133        _layout: &MeshVertexBufferLayoutRef,
134        _key: MaterialExtensionKey<Self>,
135    ) -> Result<(), SpecializedMeshPipelineError> {
136        descriptor.depth_stencil.as_mut().unwrap().depth_compare = Some(CompareFunction::Always);
137
138        descriptor.vertex.shader_defs.push("FORWARD_DECAL".into());
139
140        if let Some(fragment) = &mut descriptor.fragment {
141            fragment.shader_defs.push("FORWARD_DECAL".into());
142        }
143
144        if let Some(label) = &mut descriptor.label {
145            *label = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("forward_decal_{0}", label))
    })format!("forward_decal_{label}").into();
146        }
147
148        Ok(())
149    }
150}
151
152impl Default for ForwardDecalMaterialExt {
153    fn default() -> Self {
154        Self {
155            depth_fade_factor: 8.0,
156        }
157    }
158}
159
160#[derive(impl bevy_ecs::component::Component for ForwardDecalMesh where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {
    const STORAGE_TYPE: bevy_ecs::component::StorageType =
        bevy_ecs::component::StorageType::SparseSet;
    type Mutability = bevy_ecs::component::Mutable;
    fn register_required_components(_requiree:
            bevy_ecs::component::ComponentId,
        required_components:
            &mut bevy_ecs::component::RequiredComponentsRegistrator) {
        let resource_component_id =
            if let ::core::option::Option::Some(id) =
                    required_components.components_registrator().component_id::<ForwardDecalMesh>()
                {
                id
            } else {
                required_components.components_registrator().register_component::<ForwardDecalMesh>()
            };
        required_components.register_required::<bevy_ecs::resource::IsResource>(move
                ||
                bevy_ecs::resource::IsResource::new(resource_component_id));
    }
    fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
        use bevy_ecs::component::{
            DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
        };
        (&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
    }
    fn relationship_accessor()
        ->
            ::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
        ::core::option::Option::None
    }
}
impl bevy_ecs::resource::Resource for ForwardDecalMesh where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource)]
161struct ForwardDecalMesh(Handle<Mesh>);
162
163// Note: We need to use a hook here instead of required components since we cannot access resources
164// with required components, and we can't otherwise get a handle to the asset from a required
165// component constructor, since the constructor must be a function pointer, and we intentionally do
166// not want to use `uuid_handle!`.
167fn forward_decal_set_mesh(mut world: DeferredWorld, HookContext { entity, .. }: HookContext) {
168    let decal_mesh = world.resource::<ForwardDecalMesh>().0.clone();
169    let mut entity = world.entity_mut(entity);
170    let mut entity_mesh = entity.get_mut::<Mesh3d>().unwrap();
171    // Only replace the mesh handle if the mesh handle is defaulted.
172    if **entity_mesh == Handle::default() {
173        entity_mesh.0 = decal_mesh;
174    }
175}