Skip to main content

bevy_render/view/
mod.rs

1pub mod visibility;
2pub mod window;
3
4use bevy_camera::{
5    primitives::Frustum, CameraMainTextureUsages, ClearColor, ClearColorConfig, CompositingSpace,
6    Exposure, MainPassResolutionOverride, NormalizedRenderTarget,
7};
8use bevy_diagnostic::FrameCount;
9pub use visibility::*;
10pub use window::*;
11
12use crate::{
13    camera::{ExtractedCamera, MipBias, NormalizedRenderTargetExt as _, TemporalJitter},
14    extract_component::ExtractComponentPlugin,
15    occlusion_culling::OcclusionCulling,
16    render_asset::RenderAssets,
17    render_phase::ViewRangefinder3d,
18    render_resource::{DynamicUniformBuffer, ShaderType, Texture, TextureView},
19    renderer::{RenderDevice, RenderQueue},
20    sync_world::MainEntity,
21    texture::{
22        CachedTexture, ColorAttachment, DepthAttachment, GpuImage, ManualTextureViews,
23        OutputColorAttachment, TextureCache,
24    },
25    GpuResourceAppExt, Render, RenderApp, RenderSystems,
26};
27use alloc::sync::{Arc, Weak};
28use bevy_app::{App, Plugin};
29use bevy_color::{LinearRgba, Oklaba, Srgba};
30use bevy_derive::{Deref, DerefMut};
31use bevy_ecs::{prelude::*, VariantDefaults};
32use bevy_image::ToExtents;
33use bevy_math::{mat3, vec2, vec3, Mat3, Mat4, UVec4, Vec2, Vec3, Vec4, Vec4Swizzles};
34use bevy_platform::collections::{hash_map::Entry, HashMap};
35use bevy_reflect::{std_traits::ReflectDefault, Reflect};
36use bevy_render_macros::ExtractComponent;
37use bevy_shader::load_shader_library;
38use bevy_transform::components::GlobalTransform;
39use core::{
40    ops::Range,
41    sync::atomic::{AtomicUsize, Ordering},
42};
43use wgpu::{
44    BufferUsages, Color as WgpuColor, RenderPassColorAttachment, RenderPassDepthStencilAttachment,
45    StoreOp, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
46};
47
48/// The matrix that converts from the RGB to the LMS color space.
49///
50/// To derive this, first we convert from RGB to [CIE 1931 XYZ]:
51///
52/// ```text
53/// ⎡ X ⎤   ⎡ 0.490  0.310  0.200 ⎤ ⎡ R ⎤
54/// ⎢ Y ⎥ = ⎢ 0.177  0.812  0.011 ⎥ ⎢ G ⎥
55/// ⎣ Z ⎦   ⎣ 0.000  0.010  0.990 ⎦ ⎣ B ⎦
56/// ```
57///
58/// Then we convert to LMS according to the [CAM16 standard matrix]:
59///
60/// ```text
61/// ⎡ L ⎤   ⎡  0.401   0.650  -0.051 ⎤ ⎡ X ⎤
62/// ⎢ M ⎥ = ⎢ -0.250   1.204   0.046 ⎥ ⎢ Y ⎥
63/// ⎣ S ⎦   ⎣ -0.002   0.049   0.953 ⎦ ⎣ Z ⎦
64/// ```
65///
66/// The resulting matrix is just the concatenation of these two matrices, to do
67/// the conversion in one step.
68///
69/// [CIE 1931 XYZ]: https://en.wikipedia.org/wiki/CIE_1931_color_space
70/// [CAM16 standard matrix]: https://en.wikipedia.org/wiki/LMS_color_space
71static RGB_TO_LMS: Mat3 = mat3(
72    vec3(0.311692, 0.0905138, 0.00764433),
73    vec3(0.652085, 0.901341, 0.0486554),
74    vec3(0.0362225, 0.00814478, 0.943700),
75);
76
77/// The inverse of the [`RGB_TO_LMS`] matrix, converting from the LMS color
78/// space back to RGB.
79static LMS_TO_RGB: Mat3 = mat3(
80    vec3(4.06305, -0.40791, -0.0118812),
81    vec3(-2.93241, 1.40437, -0.0486532),
82    vec3(-0.130646, 0.00353630, 1.0605344),
83);
84
85/// The [CIE 1931] *xy* chromaticity coordinates of the [D65 white point].
86///
87/// [CIE 1931]: https://en.wikipedia.org/wiki/CIE_1931_color_space
88/// [D65 white point]: https://en.wikipedia.org/wiki/Standard_illuminant#D65_values
89static D65_XY: Vec2 = vec2(0.31272, 0.32903);
90
91/// The [D65 white point] in [LMS color space].
92///
93/// [LMS color space]: https://en.wikipedia.org/wiki/LMS_color_space
94/// [D65 white point]: https://en.wikipedia.org/wiki/Standard_illuminant#D65_values
95static D65_LMS: Vec3 = vec3(0.975538, 1.01648, 1.08475);
96
97/// Mask bits (5-bit) for use in pipeline key bitfields.
98pub const COLOR_TARGET_FORMAT_MASK_BITS: u32 = 0b11111;
99
100/// Encode a [`TextureFormat`] as a 5-bit code for use in pipeline key bitfields.
101///
102/// Covers all WebGPU renderable and blendable texture formats. Some of them need optional features.
103/// See <https://gpuweb.github.io/gpuweb/#plain-color-formats>.
104#[inline]
105pub fn texture_format_to_code(format: TextureFormat) -> Option<u8> {
106    Some(match format {
107        TextureFormat::R8Unorm => 0,
108        TextureFormat::R8Snorm => 1,
109        TextureFormat::Rg8Unorm => 2,
110        TextureFormat::Rg8Snorm => 3,
111        TextureFormat::Rgba8Unorm => 4,
112        TextureFormat::Rgba8UnormSrgb => 5,
113        TextureFormat::Rgba8Snorm => 6,
114        TextureFormat::Bgra8Unorm => 7,
115        TextureFormat::Bgra8UnormSrgb => 8,
116        TextureFormat::R16Float => 11,
117        TextureFormat::R16Unorm => 9,
118        TextureFormat::R16Snorm => 10,
119        TextureFormat::Rg16Float => 12,
120        TextureFormat::Rg16Unorm => 13,
121        TextureFormat::Rg16Snorm => 14,
122        TextureFormat::Rgba16Float => 15,
123        TextureFormat::Rgba16Unorm => 16,
124        TextureFormat::Rgba16Snorm => 17,
125        TextureFormat::R32Float => 18,
126        TextureFormat::Rg32Float => 19,
127        TextureFormat::Rgba32Float => 20,
128        TextureFormat::Rgb10a2Unorm => 21,
129        TextureFormat::Rg11b10Ufloat => 22,
130        _ => return None,
131    })
132}
133
134/// Decode a 5-bit code back into a [`TextureFormat`].
135///
136/// Inverse of [`texture_format_to_code`].
137#[inline]
138pub fn texture_format_from_code(code: u8) -> Option<TextureFormat> {
139    Some(match code {
140        0 => TextureFormat::R8Unorm,
141        1 => TextureFormat::R8Snorm,
142        2 => TextureFormat::Rg8Unorm,
143        3 => TextureFormat::Rg8Snorm,
144        4 => TextureFormat::Rgba8Unorm,
145        5 => TextureFormat::Rgba8UnormSrgb,
146        6 => TextureFormat::Rgba8Snorm,
147        7 => TextureFormat::Bgra8Unorm,
148        8 => TextureFormat::Bgra8UnormSrgb,
149        11 => TextureFormat::R16Float,
150        9 => TextureFormat::R16Unorm,
151        10 => TextureFormat::R16Snorm,
152        12 => TextureFormat::Rg16Float,
153        13 => TextureFormat::Rg16Unorm,
154        14 => TextureFormat::Rg16Snorm,
155        15 => TextureFormat::Rgba16Float,
156        16 => TextureFormat::Rgba16Unorm,
157        17 => TextureFormat::Rgba16Snorm,
158        18 => TextureFormat::R32Float,
159        19 => TextureFormat::Rg32Float,
160        20 => TextureFormat::Rgba32Float,
161        21 => TextureFormat::Rgb10a2Unorm,
162        22 => TextureFormat::Rg11b10Ufloat,
163        _ => return None,
164    })
165}
166
167pub struct ViewPlugin;
168
169impl Plugin for ViewPlugin {
170    fn build(&self, app: &mut App) {
171        {
    {
        let mut embedded =
            app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
        let path =
            {
                let crate_name =
                    "bevy_render::view".split(':').next().unwrap();
                ::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
                    "src".as_ref(), "src/view/mod.rs".as_ref(),
                    "view.wgsl".as_ref())
            };
        let watched_path =
            ::bevy_asset::io::embedded::watched_path("src/view/mod.rs",
                "view.wgsl");
        embedded.insert_asset(watched_path, &path,
            b"#define_import_path bevy_render::view\n\nstruct ColorGrading {\n    balance: mat3x3<f32>,\n    saturation: vec3<f32>,\n    contrast: vec3<f32>,\n    gamma: vec3<f32>,\n    gain: vec3<f32>,\n    lift: vec3<f32>,\n    midtone_range: vec2<f32>,\n    exposure: f32,\n    hue: f32,\n    post_saturation: f32,\n}\n\nstruct View {\n    clip_from_world: mat4x4<f32>,\n    unjittered_clip_from_world: mat4x4<f32>,\n    world_from_clip: mat4x4<f32>,\n    world_from_view: mat4x4<f32>,\n    view_from_world: mat4x4<f32>,\n    // Typically a column-major right-handed projection matrix, one of either:\n    //\n    // Perspective (infinite reverse z)\n    // ```\n    // f = 1 / tan(fov_y_radians / 2)\n    //\n    // \xe2\x8e\xa1 f / aspect  0   0     0 \xe2\x8e\xa4\n    // \xe2\x8e\xa2          0  f   0     0 \xe2\x8e\xa5\n    // \xe2\x8e\xa2          0  0   0  near \xe2\x8e\xa5\n    // \xe2\x8e\xa3          0  0  -1     0 \xe2\x8e\xa6\n    // ```\n    //\n    // Orthographic\n    // ```\n    // w = right - left\n    // h = top - bottom\n    // d = far - near\n    // cw = -right - left\n    // ch = -top - bottom\n    //\n    // \xe2\x8e\xa1 2 / w      0      0   cw / w \xe2\x8e\xa4\n    // \xe2\x8e\xa2     0  2 / h      0   ch / h \xe2\x8e\xa5\n    // \xe2\x8e\xa2     0      0  1 / d  far / d \xe2\x8e\xa5\n    // \xe2\x8e\xa3     0      0      0        1 \xe2\x8e\xa6\n    // ```\n    //\n    // `clip_from_view[3][3] == 1.0` is the standard way to check if a projection is orthographic\n    //\n    // Wgsl matrices are column major, so for example getting the near plane of a perspective projection is `clip_from_view[3][2]`\n    //\n    // Custom projections are also possible however.\n    clip_from_view: mat4x4<f32>,\n    view_from_clip: mat4x4<f32>,\n    world_position: vec3<f32>,\n    exposure: f32,\n    // viewport(x_origin, y_origin, width, height)\n    viewport: vec4<f32>,\n    main_pass_viewport: vec4<f32>,\n    // 6 world-space half spaces (normal: vec3, distance: f32) ordered left, right, top, bottom, near, far.\n    // The normal vectors point towards the interior of the frustum.\n    // A half space contains `p` if `normal.dot(p) + distance > 0.`\n    frustum: array<vec4<f32>, 6>,\n    // The world-space position of the camera used to resolve visibility ranges.\n    //\n    // This is the position of the camera itself, unless this view isn\'t\n    // associated with a camera, in which case it\'s the position of the primary\n    // camera.\n    lod_view_world_position: vec3<f32>,\n    color_grading: ColorGrading,\n    mip_bias: f32,\n    frame_count: u32,\n};\n\n/// World space:\n/// +y is up\n\n/// View space:\n/// -z is forward, +x is right, +y is up\n/// Forward is from the camera position into the scene.\n/// (0.0, 0.0, -1.0) is linear distance of 1.0 in front of the camera\'s view relative to the camera\'s rotation\n/// (0.0, 1.0, 0.0) is linear distance of 1.0 above the camera\'s view relative to the camera\'s rotation\n\n/// NDC (normalized device coordinate):\n/// https://www.w3.org/TR/webgpu/#coordinate-systems\n/// (-1.0, -1.0) in NDC is located at the bottom-left corner of NDC\n/// (1.0, 1.0) in NDC is located at the top-right corner of NDC\n/// Z is depth where:\n///    1.0 is near clipping plane\n///    Perspective projection: 0.0 is inf far away\n///    Orthographic projection: 0.0 is far clipping plane\n\n/// Clip space:\n/// This is NDC before the perspective divide, still in homogenous coordinate space.\n/// Dividing a clip space point by its w component yields a point in NDC space.\n\n/// UV space:\n/// 0.0, 0.0 is the top left\n/// 1.0, 1.0 is the bottom right\n\n\n// -----------------\n// TO WORLD --------\n// -----------------\n\n/// Convert a view space position to world space\nfn position_view_to_world(view_pos: vec3<f32>, world_from_view: mat4x4<f32>) -> vec3<f32> {\n    let world_pos = world_from_view * vec4(view_pos, 1.0);\n    return world_pos.xyz;\n}\n\n/// Convert a clip space position to world space\nfn position_clip_to_world(clip_pos: vec4<f32>, world_from_clip: mat4x4<f32>) -> vec3<f32> {\n    let world_pos = world_from_clip * clip_pos;\n    return world_pos.xyz;\n}\n\n/// Convert a ndc space position to world space\nfn position_ndc_to_world(ndc_pos: vec3<f32>, world_from_clip: mat4x4<f32>) -> vec3<f32> {\n    let world_pos = world_from_clip * vec4(ndc_pos, 1.0);\n    return world_pos.xyz / world_pos.w;\n}\n\n/// Convert a view space direction to world space\nfn direction_view_to_world(view_dir: vec3<f32>, world_from_view: mat4x4<f32>) -> vec3<f32> {\n    let world_dir = world_from_view * vec4(view_dir, 0.0);\n    return world_dir.xyz;\n}\n\n/// Convert a clip space direction to world space\nfn direction_clip_to_world(clip_dir: vec4<f32>, world_from_clip: mat4x4<f32>) -> vec3<f32> {\n    let world_dir = world_from_clip * clip_dir;\n    return world_dir.xyz;\n}\n\n// -----------------\n// TO VIEW ---------\n// -----------------\n\n/// Convert a world space position to view space\nfn position_world_to_view(world_pos: vec3<f32>, view_from_world: mat4x4<f32>) -> vec3<f32> {\n    let view_pos = view_from_world * vec4(world_pos, 1.0);\n    return view_pos.xyz;\n}\n\n/// Convert a clip space position to view space\nfn position_clip_to_view(clip_pos: vec4<f32>, view_from_clip: mat4x4<f32>) -> vec3<f32> {\n    let view_pos = view_from_clip * clip_pos;\n    return view_pos.xyz;\n}\n\n/// Convert a ndc space position to view space\nfn position_ndc_to_view(ndc_pos: vec3<f32>, view_from_clip: mat4x4<f32>) -> vec3<f32> {\n    let view_pos = view_from_clip * vec4(ndc_pos, 1.0);\n    return view_pos.xyz / view_pos.w;\n}\n\n/// Convert a world space direction to view space\nfn direction_world_to_view(world_dir: vec3<f32>, view_from_world: mat4x4<f32>) -> vec3<f32> {\n    let view_dir = view_from_world * vec4(world_dir, 0.0);\n    return view_dir.xyz;\n}\n\n/// Convert a clip space direction to view space\nfn direction_clip_to_view(clip_dir: vec4<f32>, view_from_clip: mat4x4<f32>) -> vec3<f32> {\n    let view_dir = view_from_clip * clip_dir;\n    return view_dir.xyz;\n}\n\n// -----------------\n// TO CLIP ---------\n// -----------------\n\n/// Convert a world space position to clip space\nfn position_world_to_clip(world_pos: vec3<f32>, clip_from_world: mat4x4<f32>) -> vec4<f32> {\n    let clip_pos = clip_from_world * vec4(world_pos, 1.0);\n    return clip_pos;\n}\n\n/// Convert a view space position to clip space\nfn position_view_to_clip(view_pos: vec3<f32>, clip_from_view: mat4x4<f32>) -> vec4<f32> {\n    let clip_pos = clip_from_view * vec4(view_pos, 1.0);\n    return clip_pos;\n}\n\n/// Convert a world space direction to clip space\nfn direction_world_to_clip(world_dir: vec3<f32>, clip_from_world: mat4x4<f32>) -> vec4<f32> {\n    let clip_dir = clip_from_world * vec4(world_dir, 0.0);\n    return clip_dir;\n}\n\n/// Convert a view space direction to clip space\nfn direction_view_to_clip(view_dir: vec3<f32>, clip_from_view: mat4x4<f32>) -> vec4<f32> {\n    let clip_dir = clip_from_view * vec4(view_dir, 0.0);\n    return clip_dir;\n}\n\n// -----------------\n// TO NDC ----------\n// -----------------\n\n/// Convert a world space position to ndc space\nfn position_world_to_ndc(world_pos: vec3<f32>, clip_from_world: mat4x4<f32>) -> vec3<f32> {\n    let ndc_pos = clip_from_world * vec4(world_pos, 1.0);\n    return ndc_pos.xyz / ndc_pos.w;\n}\n\n/// Convert a view space position to ndc space\nfn position_view_to_ndc(view_pos: vec3<f32>, clip_from_view: mat4x4<f32>) -> vec3<f32> {\n    let ndc_pos = clip_from_view * vec4(view_pos, 1.0);\n    return ndc_pos.xyz / ndc_pos.w;\n}\n\n// -----------------\n// DEPTH -----------\n// -----------------\n\n/// Retrieve the perspective camera near clipping plane\nfn perspective_camera_near(clip_from_view: mat4x4<f32>) -> f32 {\n    return clip_from_view[3][2];\n}\n\n/// Convert ndc depth to linear view z.\n/// Note: Depth values in front of the camera will be negative as -z is forward\nfn depth_ndc_to_view_z(ndc_depth: f32, clip_from_view: mat4x4<f32>, view_from_clip: mat4x4<f32>) -> f32 {\n#ifdef VIEW_PROJECTION_PERSPECTIVE\n    return -perspective_camera_near(clip_from_view) / ndc_depth;\n#else ifdef VIEW_PROJECTION_ORTHOGRAPHIC\n    return -(clip_from_view[3][2] - ndc_depth) / clip_from_view[2][2];\n#else\n    let view_pos = view_from_clip * vec4(0.0, 0.0, ndc_depth, 1.0);\n    return view_pos.z / view_pos.w;\n#endif\n}\n\n/// Convert linear view z to ndc depth.\n/// Note: View z input should be negative for values in front of the camera as -z is forward\nfn view_z_to_depth_ndc(view_z: f32, clip_from_view: mat4x4<f32>) -> f32 {\n#ifdef VIEW_PROJECTION_PERSPECTIVE\n    return -perspective_camera_near(clip_from_view) / view_z;\n#else ifdef VIEW_PROJECTION_ORTHOGRAPHIC\n    return clip_from_view[3][2] + view_z * clip_from_view[2][2];\n#else\n    let ndc_pos = clip_from_view * vec4(0.0, 0.0, view_z, 1.0);\n    return ndc_pos.z / ndc_pos.w;\n#endif\n}\n\n// -----------------\n// UV --------------\n// -----------------\n\n/// Convert ndc space xy coordinate [-1.0 .. 1.0] to uv [0.0 .. 1.0]\nfn ndc_to_uv(ndc: vec2<f32>) -> vec2<f32> {\n    return ndc * vec2(0.5, -0.5) + vec2(0.5);\n}\n\n/// Convert uv [0.0 .. 1.0] coordinate to ndc space xy [-1.0 .. 1.0]\nfn uv_to_ndc(uv: vec2<f32>) -> vec2<f32> {\n    return uv * vec2(2.0, -2.0) + vec2(-1.0, 1.0);\n}\n\n/// returns the (0.0, 0.0) .. (1.0, 1.0) position within the viewport for the current render target\n/// [0 .. render target viewport size] eg. [(0.0, 0.0) .. (1280.0, 720.0)] to [(0.0, 0.0) .. (1.0, 1.0)]\nfn frag_coord_to_uv(frag_coord: vec2<f32>, viewport: vec4<f32>) -> vec2<f32> {\n    return (frag_coord - viewport.xy) / viewport.zw;\n}\n\n/// Convert frag coord to ndc\nfn frag_coord_to_ndc(frag_coord: vec4<f32>, viewport: vec4<f32>) -> vec3<f32> {\n    return vec3(uv_to_ndc(frag_coord_to_uv(frag_coord.xy, viewport)), frag_coord.z);\n}\n\n/// Convert ndc space xy coordinate [-1.0 .. 1.0] to [0 .. render target\n/// viewport size]\nfn ndc_to_frag_coord(ndc: vec2<f32>, viewport: vec4<f32>) -> vec2<f32> {\n    return ndc_to_uv(ndc) * viewport.zw;\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_render::view".split(':').next().unwrap();
                            ::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
                                "src".as_ref(), "src/view/mod.rs".as_ref(),
                                "view.wgsl".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, "view.wgsl");
172
173        app
174            // NOTE: windows.is_changed() handles cases where a window was resized
175            .add_plugins((
176                ExtractComponentPlugin::<Msaa>::default(),
177                ExtractComponentPlugin::<OcclusionCulling>::default(),
178                RenderVisibilityRangePlugin,
179            ));
180
181        if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
182            render_app.add_systems(
183                Render,
184                (
185                    // `TextureView`s need to be dropped before reconfiguring window surfaces.
186                    clear_view_attachments
187                        .in_set(RenderSystems::PrepareViews)
188                        .before(create_surfaces),
189                    cleanup_view_targets_for_resize
190                        .in_set(RenderSystems::PrepareViews)
191                        .before(create_surfaces),
192                    prepare_view_attachments
193                        .in_set(RenderSystems::PrepareViews)
194                        .before(prepare_view_targets)
195                        .after(prepare_windows),
196                    prepare_view_targets
197                        .in_set(RenderSystems::PrepareViews)
198                        .after(prepare_windows)
199                        .after(crate::render_asset::prepare_assets::<GpuImage>)
200                        .ambiguous_with(crate::camera::sort_cameras), // doesn't use `sorted_camera_index_for_target`
201                    prepare_view_uniforms.in_set(RenderSystems::PrepareResources),
202                    collect_visible_cpu_culled_entities.in_set(RenderSystems::PrepareAssets),
203                ),
204            );
205        }
206    }
207
208    fn finish(&self, app: &mut App) {
209        if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
210            render_app
211                .init_gpu_resource::<ViewUniforms>()
212                .init_gpu_resource::<ViewTargetAttachments>();
213        }
214    }
215}
216
217/// Component for configuring the number of samples for [Multi-Sample Anti-Aliasing](https://en.wikipedia.org/wiki/Multisample_anti-aliasing)
218/// for a [`Camera`](bevy_camera::Camera).
219///
220/// Defaults to 4 samples. A higher number of samples results in smoother edges.
221///
222/// Some advanced rendering features may require that MSAA is disabled.
223///
224/// Note that the web currently only supports 1 or 4 samples.
225#[derive(
226    impl bevy_ecs::component::Component for Msaa 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) {}
    fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
        use bevy_ecs::component::{
            DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
        };
        (&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
    }
    fn map_entities<M: bevy_ecs::entity::EntityMapper>(this: &mut Self,
        mapper: &mut M) {
        use bevy_ecs::entity::MapEntities;
        match this {
            Self::Off { .. } => {}
            Self::Sample2 { .. } => {}
            Self::Sample4 { .. } => {}
            Self::Sample8 { .. } => {}
            _ => {}
        }
    }
    fn relationship_accessor()
        ->
            ::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
        ::core::option::Option::None
    }
}Component,
227    #[automatically_derived]
impl ::core::default::Default for Msaa {
    #[inline]
    fn default() -> Msaa { Self::Sample4 }
}Default,
228    #[automatically_derived]
impl ::core::clone::Clone for Msaa {
    #[inline]
    fn clone(&self) -> Msaa { *self }
}Clone,
229    #[automatically_derived]
impl ::core::marker::Copy for Msaa { }Copy,
230    impl bevy_render::extract_component::ExtractComponent for Msaa where
    Self: ::core::clone::Clone {
    type QueryData = &'static Self;
    type QueryFilter = ();
    type Out = Self;
    fn extract_component(item:
            bevy_ecs::query::QueryItem<'_, '_, Self::QueryData>)
        -> ::core::option::Option<Self::Out> {
        ::core::option::Option::Some(item.clone())
    }
}ExtractComponent,
231    const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for Msaa where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration.register_type_data::<ReflectComponent, Self>();
                registration.register_type_data::<ReflectDefault, Self>();
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {}
        }
        impl bevy_reflect::Typed for Msaa where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Off")),
                                                bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Sample2")),
                                                bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Sample4")),
                                                bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Sample8"))]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for Msaa where  {
            fn type_path() -> &'static str { "bevy_render::view::Msaa" }
            fn short_type_path() -> &'static str { "Msaa" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("Msaa")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_render::view".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_render::view")
            }
        }
        impl bevy_reflect::Reflect for Msaa 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(())
            }
        }
        impl bevy_reflect::func::args::GetOwnership for Msaa where  {
            fn ownership() -> bevy_reflect::func::args::Ownership {
                bevy_reflect::func::args::Ownership::Owned
            }
        }
        impl bevy_reflect::func::args::FromArg for Msaa where  {
            type This<'from_arg> = Msaa;
            fn from_arg(arg: bevy_reflect::func::args::Arg)
                ->
                    ::core::result::Result<Self::This<'_>,
                    bevy_reflect::func::args::ArgError> {
                arg.take_owned()
            }
        }
        impl bevy_reflect::func::IntoReturn for Msaa where  {
            fn into_return<'into_return>(self)
                -> bevy_reflect::func::Return<'into_return> where
                Self: 'into_return {
                bevy_reflect::func::Return::Owned(bevy_reflect::__macro_exports::alloc_utils::Box::new(self))
            }
        }
        #[allow(non_upper_case_globals)]
        const _: () =
            {
                static __INVENTORY: ::inventory::Node =
                    ::inventory::Node {
                        value: &{
                                bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<Msaa
                                        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::enums::Enum for Msaa where  {
            fn field(&self, __name_param: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at(&self, __index_param: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_mut(&mut self, __name_param: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at_mut(&mut self, __index_param: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn index_of(&self, __name_param: &str)
                -> ::core::option::Option<usize> {
                match self { _ => ::core::option::Option::None, }
            }
            fn name_at(&self, __index_param: usize)
                -> ::core::option::Option<&str> {
                match self { _ => ::core::option::Option::None, }
            }
            fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
                bevy_reflect::enums::VariantFieldIter::new(self)
            }
            #[inline]
            fn field_len(&self) -> usize {
                match self {
                    Msaa::Off { .. } => 0usize,
                    Msaa::Sample2 { .. } => 0usize,
                    Msaa::Sample4 { .. } => 0usize,
                    Msaa::Sample8 { .. } => 0usize,
                    _ => 0,
                }
            }
            #[inline]
            fn variant_name(&self) -> &str {
                match self {
                    Msaa::Off { .. } => "Off",
                    Msaa::Sample2 { .. } => "Sample2",
                    Msaa::Sample4 { .. } => "Sample4",
                    Msaa::Sample8 { .. } => "Sample8",
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_index(&self) -> usize {
                match self {
                    Msaa::Off { .. } => 0usize,
                    Msaa::Sample2 { .. } => 1usize,
                    Msaa::Sample4 { .. } => 2usize,
                    Msaa::Sample8 { .. } => 3usize,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_type(&self) -> bevy_reflect::enums::VariantType {
                match self {
                    Msaa::Off { .. } => bevy_reflect::enums::VariantType::Unit,
                    Msaa::Sample2 { .. } =>
                        bevy_reflect::enums::VariantType::Unit,
                    Msaa::Sample4 { .. } =>
                        bevy_reflect::enums::VariantType::Unit,
                    Msaa::Sample8 { .. } =>
                        bevy_reflect::enums::VariantType::Unit,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            fn to_dynamic_enum(&self) -> bevy_reflect::enums::DynamicEnum {
                bevy_reflect::enums::DynamicEnum::from_ref::<Self>(self)
            }
        }
        impl bevy_reflect::PartialReflect for Msaa 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_param: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Enum(__value_param) =
                        bevy_reflect::PartialReflect::reflect_ref(__value_param) {
                    if bevy_reflect::enums::Enum::variant_name(self) ==
                            bevy_reflect::enums::Enum::variant_name(__value_param) {
                        match bevy_reflect::enums::Enum::variant_type(__value_param)
                            {
                            bevy_reflect::enums::VariantType::Struct => {
                                for field in
                                    bevy_reflect::enums::Enum::iter_fields(__value_param) {
                                    let name = field.name().unwrap();
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_mut(self, name) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            bevy_reflect::enums::VariantType::Tuple => {
                                for (index, field) in
                                    ::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
                                    {
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_at_mut(self, index) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            _ => {}
                        }
                    } else {
                        match bevy_reflect::enums::Enum::variant_name(__value_param)
                            {
                            "Off" => { *self = Msaa::Off {} }
                            "Sample2" => { *self = Msaa::Sample2 {} }
                            "Sample4" => { *self = Msaa::Sample4 {} }
                            "Sample8" => { *self = Msaa::Sample8 {} }
                            name => {
                                return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
                                            enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
                                            variant_name: ::core::convert::Into::into(name),
                                        });
                            }
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
                                to_kind: bevy_reflect::ReflectKind::Enum,
                            });
                }
                ::core::result::Result::Ok(())
            }
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Enum
            }
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Enum(self)
            }
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Enum(self)
            }
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Enum(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_hash(&self) -> ::core::option::Option<u64> {
                use ::core::hash::{Hash, Hasher};
                let mut hasher = bevy_reflect::utility::reflect_hasher();
                Hash::hash(&::core::any::Any::type_id(self), &mut hasher);
                Hash::hash(self, &mut hasher);
                ::core::option::Option::Some(Hasher::finish(&hasher))
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                let value =
                    <dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
                if let ::core::option::Option::Some(value) = value {
                    ::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
                            value))
                } else { ::core::option::Option::Some(false) }
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::enums::enum_partial_cmp)(self, value)
            }
            fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
                -> ::core::fmt::Result {
                ::core::fmt::Debug::fmt(self, f)
            }
            #[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> {
                let this = self;
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(match this
                            {
                            Msaa::Off {} => Msaa::Off {},
                            Msaa::Sample2 {} => Msaa::Sample2 {},
                            Msaa::Sample4 {} => Msaa::Sample4 {},
                            Msaa::Sample8 {} => Msaa::Sample8 {},
                        }))
            }
        }
        impl bevy_reflect::FromReflect for Msaa where  {
            fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Enum(__param0) =
                        bevy_reflect::PartialReflect::reflect_ref(__param0) {
                    match bevy_reflect::enums::Enum::variant_name(__param0) {
                        "Off" => ::core::option::Option::Some(Msaa::Off {}),
                        "Sample2" => ::core::option::Option::Some(Msaa::Sample2 {}),
                        "Sample4" => ::core::option::Option::Some(Msaa::Sample4 {}),
                        "Sample8" => ::core::option::Option::Some(Msaa::Sample8 {}),
                        name => ::core::option::Option::None,
                    }
                } else { ::core::option::Option::None }
            }
        }
    };Reflect,
232    #[automatically_derived]
impl ::core::cmp::PartialEq for Msaa {
    #[inline]
    fn eq(&self, other: &Msaa) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq,
233    #[automatically_derived]
impl ::core::cmp::PartialOrd for Msaa {
    #[inline]
    fn partial_cmp(&self, other: &Msaa)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}PartialOrd,
234    impl Msaa {
    #[allow(missing_docs)]
    pub fn default_off() -> Self { Self::Off }
    #[allow(missing_docs)]
    pub fn default_sample2() -> Self { Self::Sample2 }
    #[allow(missing_docs)]
    pub fn default_sample4() -> Self { Self::Sample4 }
    #[allow(missing_docs)]
    pub fn default_sample8() -> Self { Self::Sample8 }
}VariantDefaults,
235    #[automatically_derived]
impl ::core::cmp::Eq for Msaa {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq,
236    #[automatically_derived]
impl ::core::hash::Hash for Msaa {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash,
237    #[automatically_derived]
impl ::core::fmt::Debug for Msaa {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                Msaa::Off => "Off",
                Msaa::Sample2 => "Sample2",
                Msaa::Sample4 => "Sample4",
                Msaa::Sample8 => "Sample8",
            })
    }
}Debug,
238)]
239#[reflect(Component, Default, PartialEq, Hash, Debug)]
240pub enum Msaa {
241    Off = 1,
242    Sample2 = 2,
243    #[default]
244    Sample4 = 4,
245    Sample8 = 8,
246}
247
248impl Msaa {
249    #[inline]
250    pub fn samples(&self) -> u32 {
251        *self as u32
252    }
253
254    pub fn from_samples(samples: u32) -> Self {
255        match samples {
256            1 => Msaa::Off,
257            2 => Msaa::Sample2,
258            4 => Msaa::Sample4,
259            8 => Msaa::Sample8,
260            _ => {
    ::core::panicking::panic_fmt(format_args!("Unsupported MSAA sample count: {0}",
            samples));
}panic!("Unsupported MSAA sample count: {samples}"),
261        }
262    }
263}
264
265/// An identifier for a view that is stable across frames.
266///
267/// We can't use [`Entity`] for this because render world entities aren't
268/// stable, and we can't use just [`MainEntity`] because some main world views
269/// extract to multiple render world views. For example, a directional light
270/// extracts to one render world view per cascade, and a point light extracts to
271/// one render world view per cubemap face. So we pair the main entity with an
272/// *auxiliary entity* and a *subview index*, which *together* uniquely identify
273/// a view in the render world in a way that's stable from frame to frame.
274#[derive(#[automatically_derived]
impl ::core::clone::Clone for RetainedViewEntity {
    #[inline]
    fn clone(&self) -> RetainedViewEntity {
        let _: ::core::clone::AssertParamIsClone<MainEntity>;
        let _: ::core::clone::AssertParamIsClone<u32>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for RetainedViewEntity { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for RetainedViewEntity {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "RetainedViewEntity", "main_entity", &self.main_entity,
            "auxiliary_entity", &self.auxiliary_entity, "subview_index",
            &&self.subview_index)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for RetainedViewEntity {
    #[inline]
    fn eq(&self, other: &RetainedViewEntity) -> bool {
        self.subview_index == other.subview_index &&
                self.main_entity == other.main_entity &&
            self.auxiliary_entity == other.auxiliary_entity
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for RetainedViewEntity {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<MainEntity>;
        let _: ::core::cmp::AssertParamIsEq<u32>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for RetainedViewEntity {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.main_entity, state);
        ::core::hash::Hash::hash(&self.auxiliary_entity, state);
        ::core::hash::Hash::hash(&self.subview_index, state)
    }
}Hash)]
275pub struct RetainedViewEntity {
276    /// The main entity that this view corresponds to.
277    pub main_entity: MainEntity,
278
279    /// Another entity associated with the view entity.
280    ///
281    /// This is currently used for shadow cascades. If there are multiple
282    /// cameras, each camera needs to have its own set of shadow cascades. Thus
283    /// the light and subview index aren't themselves enough to uniquely
284    /// identify a shadow cascade: we need the camera that the cascade is
285    /// associated with as well. This entity stores that camera.
286    ///
287    /// If not present, this will be `MainEntity(Entity::PLACEHOLDER)`.
288    pub auxiliary_entity: MainEntity,
289
290    /// The index of the view corresponding to the entity.
291    ///
292    /// For example, for point lights that cast shadows, this is the index of
293    /// the cubemap face (0 through 5 inclusive). For directional lights, this
294    /// is the index of the cascade.
295    pub subview_index: u32,
296}
297
298impl RetainedViewEntity {
299    /// Creates a new [`RetainedViewEntity`] from the given main world entity,
300    /// auxiliary main world entity, and subview index.
301    ///
302    /// See [`RetainedViewEntity::subview_index`] for an explanation of what
303    /// `auxiliary_entity` and `subview_index` are.
304    pub fn new(
305        main_entity: MainEntity,
306        auxiliary_entity: Option<MainEntity>,
307        subview_index: u32,
308    ) -> Self {
309        Self {
310            main_entity,
311            auxiliary_entity: auxiliary_entity.unwrap_or(Entity::PLACEHOLDER.into()),
312            subview_index,
313        }
314    }
315}
316
317/// Describes a view in the render world.
318///
319/// Each entity in the main world can potentially extract to multiple views,
320/// each of which have a [`RetainedViewEntity::subview_index`].
321/// For instance, point lights with shadows extract to 6 subviews,
322/// one for each side of the shadow cubemap.
323/// [`Camera3d`](bevy_camera::Camera3d) extracts into a [`ExtractedView`]
324/// and [`ExtractedCamera`] component.
325#[derive(impl bevy_ecs::component::Component for ExtractedView 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) {}
    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)]
326pub struct ExtractedView {
327    /// The entity in the main world corresponding to this render world view.
328    pub retained_view_entity: RetainedViewEntity,
329    /// Typically a column-major right-handed projection matrix, one of either:
330    ///
331    /// Perspective (infinite reverse z)
332    /// ```text
333    /// f = 1 / tan(fov_y_radians / 2)
334    ///
335    /// ⎡ f / aspect  0   0     0 ⎤
336    /// ⎢          0  f   0     0 ⎥
337    /// ⎢          0  0   0  near ⎥
338    /// ⎣          0  0  -1     0 ⎦
339    /// ```
340    ///
341    /// Orthographic
342    /// ```text
343    /// w = right - left
344    /// h = top - bottom
345    /// d = far - near
346    /// cw = -right - left
347    /// ch = -top - bottom
348    ///
349    /// ⎡ 2 / w      0      0   cw / w ⎤
350    /// ⎢     0  2 / h      0   ch / h ⎥
351    /// ⎢     0      0  1 / d  far / d ⎥
352    /// ⎣     0      0      0        1 ⎦
353    /// ```
354    ///
355    /// `clip_from_view[3][3] == 1.0` is the standard way to check if a projection is orthographic
356    ///
357    /// Glam matrices are column major, so for example getting the near plane of a perspective projection is `clip_from_view[3][2]`
358    ///
359    /// Custom projections are also possible however.
360    pub clip_from_view: Mat4,
361    pub world_from_view: GlobalTransform,
362    // The view-projection matrix. When provided it is used instead of deriving it from
363    // `projection` and `transform` fields, which can be helpful in cases where numerical
364    // stability matters and there is a more direct way to derive the view-projection matrix.
365    pub clip_from_world: Option<Mat4>,
366    /// The [`TextureFormat`] this view will render to. Note that this may diverge from
367    /// the [`RenderTarget`](bevy_camera::RenderTarget)'s texture format. Among other
368    /// reasons, [`Hdr`](bevy_camera::Hdr) sets an the internal render target format
369    /// override to ensure sufficient precision is present for lighting calculations.
370    pub target_format: TextureFormat,
371    // uvec4(origin.x, origin.y, width, height)
372    pub viewport: UVec4,
373    pub color_grading: ColorGrading,
374
375    /// Whether to switch culling mode so that materials that request backface
376    /// culling cull front faces, and vice versa.
377    ///
378    /// This is typically used for cameras that mirror the world that they
379    /// render across a plane, because doing that flips the winding of each
380    /// polygon.
381    ///
382    /// This setting doesn't affect materials that disable backface culling.
383    pub invert_culling: bool,
384}
385
386impl ExtractedView {
387    /// Creates a 3D rangefinder for a view
388    pub fn rangefinder3d(&self) -> ViewRangefinder3d {
389        ViewRangefinder3d::from_world_from_view(&self.world_from_view.affine())
390    }
391}
392
393/// Configures filmic color grading parameters to adjust the image appearance.
394///
395/// Color grading is applied just before tonemapping for a given
396/// [`Camera`](bevy_camera::Camera) entity, with the sole exception of the
397/// `post_saturation` value in [`ColorGradingGlobal`], which is applied after
398/// tonemapping.
399#[derive(impl bevy_ecs::component::Component for ColorGrading 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) {}
    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 ColorGrading where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration.register_type_data::<ReflectComponent, Self>();
                registration.register_type_data::<ReflectDefault, Self>();
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <ColorGradingGlobal as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <ColorGradingSection as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for ColorGrading where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<ColorGradingGlobal>("global"),
                                                bevy_reflect::NamedField::new::<ColorGradingSection>("shadows"),
                                                bevy_reflect::NamedField::new::<ColorGradingSection>("midtones"),
                                                bevy_reflect::NamedField::new::<ColorGradingSection>("highlights")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for ColorGrading where  {
            fn type_path() -> &'static str {
                "bevy_render::view::ColorGrading"
            }
            fn short_type_path() -> &'static str { "ColorGrading" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("ColorGrading")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_render::view".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_render::view")
            }
        }
        impl bevy_reflect::Reflect for ColorGrading 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(())
            }
        }
        impl bevy_reflect::func::args::GetOwnership for ColorGrading where  {
            fn ownership() -> bevy_reflect::func::args::Ownership {
                bevy_reflect::func::args::Ownership::Owned
            }
        }
        impl bevy_reflect::func::args::FromArg for ColorGrading where  {
            type This<'from_arg> = ColorGrading;
            fn from_arg(arg: bevy_reflect::func::args::Arg)
                ->
                    ::core::result::Result<Self::This<'_>,
                    bevy_reflect::func::args::ArgError> {
                arg.take_owned()
            }
        }
        impl bevy_reflect::func::IntoReturn for ColorGrading where  {
            fn into_return<'into_return>(self)
                -> bevy_reflect::func::Return<'into_return> where
                Self: 'into_return {
                bevy_reflect::func::Return::Owned(bevy_reflect::__macro_exports::alloc_utils::Box::new(self))
            }
        }
        #[allow(non_upper_case_globals)]
        const _: () =
            {
                static __INVENTORY: ::inventory::Node =
                    ::inventory::Node {
                        value: &{
                                bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<ColorGrading
                                        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 ColorGrading where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "global" => ::core::option::Option::Some(&self.global),
                    "shadows" => ::core::option::Option::Some(&self.shadows),
                    "midtones" => ::core::option::Option::Some(&self.midtones),
                    "highlights" =>
                        ::core::option::Option::Some(&self.highlights),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "global" => ::core::option::Option::Some(&mut self.global),
                    "shadows" =>
                        ::core::option::Option::Some(&mut self.shadows),
                    "midtones" =>
                        ::core::option::Option::Some(&mut self.midtones),
                    "highlights" =>
                        ::core::option::Option::Some(&mut self.highlights),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&self.global),
                    1usize => ::core::option::Option::Some(&self.shadows),
                    2usize => ::core::option::Option::Some(&self.midtones),
                    3usize => ::core::option::Option::Some(&self.highlights),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&mut self.global),
                    1usize => ::core::option::Option::Some(&mut self.shadows),
                    2usize => ::core::option::Option::Some(&mut self.midtones),
                    3usize =>
                        ::core::option::Option::Some(&mut self.highlights),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("global"),
                    1usize => ::core::option::Option::Some("shadows"),
                    2usize => ::core::option::Option::Some("midtones"),
                    3usize => ::core::option::Option::Some("highlights"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "global" => ::core::option::Option::Some(0usize),
                    "shadows" => ::core::option::Option::Some(1usize),
                    "midtones" => ::core::option::Option::Some(2usize),
                    "highlights" => ::core::option::Option::Some(3usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 4usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                -> bevy_reflect::structs::DynamicStruct {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("global",
                    bevy_reflect::PartialReflect::to_dynamic(&self.global));
                dynamic.insert_boxed("shadows",
                    bevy_reflect::PartialReflect::to_dynamic(&self.shadows));
                dynamic.insert_boxed("midtones",
                    bevy_reflect::PartialReflect::to_dynamic(&self.midtones));
                dynamic.insert_boxed("highlights",
                    bevy_reflect::PartialReflect::to_dynamic(&self.highlights));
                dynamic
            }
        }
        impl bevy_reflect::PartialReflect for ColorGrading 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)
            }
            fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
                -> ::core::fmt::Result {
                ::core::fmt::Debug::fmt(self, f)
            }
            #[inline]
            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(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for ColorGrading 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 mut __this =
                        <Self as ::core::default::Default>::default();
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <ColorGradingGlobal as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "global")?))() {
                        __this.global = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <ColorGradingSection as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "shadows")?))() {
                        __this.shadows = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <ColorGradingSection as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "midtones")?))() {
                        __this.midtones = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <ColorGradingSection as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "highlights")?))() {
                        __this.highlights = __field;
                    }
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect, #[automatically_derived]
impl ::core::fmt::Debug for ColorGrading {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f, "ColorGrading",
            "global", &self.global, "shadows", &self.shadows, "midtones",
            &self.midtones, "highlights", &&self.highlights)
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for ColorGrading {
    #[inline]
    fn default() -> ColorGrading {
        ColorGrading {
            global: ::core::default::Default::default(),
            shadows: ::core::default::Default::default(),
            midtones: ::core::default::Default::default(),
            highlights: ::core::default::Default::default(),
        }
    }
}Default, #[automatically_derived]
impl ::core::clone::Clone for ColorGrading {
    #[inline]
    fn clone(&self) -> ColorGrading {
        ColorGrading {
            global: ::core::clone::Clone::clone(&self.global),
            shadows: ::core::clone::Clone::clone(&self.shadows),
            midtones: ::core::clone::Clone::clone(&self.midtones),
            highlights: ::core::clone::Clone::clone(&self.highlights),
        }
    }
}Clone)]
400#[reflect(Component, Default, Debug, Clone)]
401pub struct ColorGrading {
402    /// Filmic color grading values applied to the image as a whole (as opposed
403    /// to individual sections, like shadows and highlights).
404    pub global: ColorGradingGlobal,
405
406    /// Color grading values that are applied to the darker parts of the image.
407    ///
408    /// The cutoff points can be customized with the
409    /// [`ColorGradingGlobal::midtones_range`] field.
410    pub shadows: ColorGradingSection,
411
412    /// Color grading values that are applied to the parts of the image with
413    /// intermediate brightness.
414    ///
415    /// The cutoff points can be customized with the
416    /// [`ColorGradingGlobal::midtones_range`] field.
417    pub midtones: ColorGradingSection,
418
419    /// Color grading values that are applied to the lighter parts of the image.
420    ///
421    /// The cutoff points can be customized with the
422    /// [`ColorGradingGlobal::midtones_range`] field.
423    pub highlights: ColorGradingSection,
424}
425
426/// Filmic color grading values applied to the image as a whole (as opposed to
427/// individual sections, like shadows and highlights).
428#[derive(#[automatically_derived]
impl ::core::clone::Clone for ColorGradingGlobal {
    #[inline]
    fn clone(&self) -> ColorGradingGlobal {
        ColorGradingGlobal {
            exposure: ::core::clone::Clone::clone(&self.exposure),
            temperature: ::core::clone::Clone::clone(&self.temperature),
            tint: ::core::clone::Clone::clone(&self.tint),
            hue: ::core::clone::Clone::clone(&self.hue),
            post_saturation: ::core::clone::Clone::clone(&self.post_saturation),
            midtones_range: ::core::clone::Clone::clone(&self.midtones_range),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for ColorGradingGlobal {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["exposure", "temperature", "tint", "hue", "post_saturation",
                        "midtones_range"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.exposure, &self.temperature, &self.tint, &self.hue,
                        &self.post_saturation, &&self.midtones_range];
        ::core::fmt::Formatter::debug_struct_fields_finish(f,
            "ColorGradingGlobal", names, values)
    }
}Debug, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for ColorGradingGlobal where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration.register_type_data::<ReflectDefault, Self>();
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <f32 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Range<f32> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for ColorGradingGlobal where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<f32>("exposure"),
                                                bevy_reflect::NamedField::new::<f32>("temperature"),
                                                bevy_reflect::NamedField::new::<f32>("tint"),
                                                bevy_reflect::NamedField::new::<f32>("hue"),
                                                bevy_reflect::NamedField::new::<f32>("post_saturation"),
                                                bevy_reflect::NamedField::new::<Range<f32>>("midtones_range")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for ColorGradingGlobal where  {
            fn type_path() -> &'static str {
                "bevy_render::view::ColorGradingGlobal"
            }
            fn short_type_path() -> &'static str { "ColorGradingGlobal" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("ColorGradingGlobal")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_render::view".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_render::view")
            }
        }
        impl bevy_reflect::Reflect for ColorGradingGlobal 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(())
            }
        }
        impl bevy_reflect::func::args::GetOwnership for ColorGradingGlobal
            where  {
            fn ownership() -> bevy_reflect::func::args::Ownership {
                bevy_reflect::func::args::Ownership::Owned
            }
        }
        impl bevy_reflect::func::args::FromArg for ColorGradingGlobal where  {
            type This<'from_arg> = ColorGradingGlobal;
            fn from_arg(arg: bevy_reflect::func::args::Arg)
                ->
                    ::core::result::Result<Self::This<'_>,
                    bevy_reflect::func::args::ArgError> {
                arg.take_owned()
            }
        }
        impl bevy_reflect::func::IntoReturn for ColorGradingGlobal where  {
            fn into_return<'into_return>(self)
                -> bevy_reflect::func::Return<'into_return> where
                Self: 'into_return {
                bevy_reflect::func::Return::Owned(bevy_reflect::__macro_exports::alloc_utils::Box::new(self))
            }
        }
        #[allow(non_upper_case_globals)]
        const _: () =
            {
                static __INVENTORY: ::inventory::Node =
                    ::inventory::Node {
                        value: &{
                                bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<ColorGradingGlobal
                                        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 ColorGradingGlobal where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "exposure" => ::core::option::Option::Some(&self.exposure),
                    "temperature" =>
                        ::core::option::Option::Some(&self.temperature),
                    "tint" => ::core::option::Option::Some(&self.tint),
                    "hue" => ::core::option::Option::Some(&self.hue),
                    "post_saturation" =>
                        ::core::option::Option::Some(&self.post_saturation),
                    "midtones_range" =>
                        ::core::option::Option::Some(&self.midtones_range),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "exposure" =>
                        ::core::option::Option::Some(&mut self.exposure),
                    "temperature" =>
                        ::core::option::Option::Some(&mut self.temperature),
                    "tint" => ::core::option::Option::Some(&mut self.tint),
                    "hue" => ::core::option::Option::Some(&mut self.hue),
                    "post_saturation" =>
                        ::core::option::Option::Some(&mut self.post_saturation),
                    "midtones_range" =>
                        ::core::option::Option::Some(&mut self.midtones_range),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&self.exposure),
                    1usize => ::core::option::Option::Some(&self.temperature),
                    2usize => ::core::option::Option::Some(&self.tint),
                    3usize => ::core::option::Option::Some(&self.hue),
                    4usize =>
                        ::core::option::Option::Some(&self.post_saturation),
                    5usize =>
                        ::core::option::Option::Some(&self.midtones_range),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&mut self.exposure),
                    1usize =>
                        ::core::option::Option::Some(&mut self.temperature),
                    2usize => ::core::option::Option::Some(&mut self.tint),
                    3usize => ::core::option::Option::Some(&mut self.hue),
                    4usize =>
                        ::core::option::Option::Some(&mut self.post_saturation),
                    5usize =>
                        ::core::option::Option::Some(&mut self.midtones_range),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("exposure"),
                    1usize => ::core::option::Option::Some("temperature"),
                    2usize => ::core::option::Option::Some("tint"),
                    3usize => ::core::option::Option::Some("hue"),
                    4usize => ::core::option::Option::Some("post_saturation"),
                    5usize => ::core::option::Option::Some("midtones_range"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "exposure" => ::core::option::Option::Some(0usize),
                    "temperature" => ::core::option::Option::Some(1usize),
                    "tint" => ::core::option::Option::Some(2usize),
                    "hue" => ::core::option::Option::Some(3usize),
                    "post_saturation" => ::core::option::Option::Some(4usize),
                    "midtones_range" => ::core::option::Option::Some(5usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 6usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                -> bevy_reflect::structs::DynamicStruct {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("exposure",
                    bevy_reflect::PartialReflect::to_dynamic(&self.exposure));
                dynamic.insert_boxed("temperature",
                    bevy_reflect::PartialReflect::to_dynamic(&self.temperature));
                dynamic.insert_boxed("tint",
                    bevy_reflect::PartialReflect::to_dynamic(&self.tint));
                dynamic.insert_boxed("hue",
                    bevy_reflect::PartialReflect::to_dynamic(&self.hue));
                dynamic.insert_boxed("post_saturation",
                    bevy_reflect::PartialReflect::to_dynamic(&self.post_saturation));
                dynamic.insert_boxed("midtones_range",
                    bevy_reflect::PartialReflect::to_dynamic(&self.midtones_range));
                dynamic
            }
        }
        impl bevy_reflect::PartialReflect for ColorGradingGlobal 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]
            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(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for ColorGradingGlobal 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 mut __this =
                        <Self as ::core::default::Default>::default();
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <f32 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "exposure")?))() {
                        __this.exposure = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <f32 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "temperature")?))() {
                        __this.temperature = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <f32 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "tint")?))() {
                        __this.tint = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <f32 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "hue")?))() {
                        __this.hue = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <f32 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "post_saturation")?))() {
                        __this.post_saturation = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <Range<f32> as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "midtones_range")?))() {
                        __this.midtones_range = __field;
                    }
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect)]
429#[reflect(Default, Clone)]
430pub struct ColorGradingGlobal {
431    /// Exposure value (EV) offset, measured in stops.
432    pub exposure: f32,
433
434    /// An adjustment made to the [CIE 1931] chromaticity *x* value.
435    ///
436    /// Positive values make the colors redder. Negative values make the colors
437    /// bluer. This has no effect on luminance (brightness).
438    ///
439    /// [CIE 1931]: https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space
440    pub temperature: f32,
441
442    /// An adjustment made to the [CIE 1931] chromaticity *y* value.
443    ///
444    /// Positive values make the colors more magenta. Negative values make the
445    /// colors greener. This has no effect on luminance (brightness).
446    ///
447    /// [CIE 1931]: https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space
448    pub tint: f32,
449
450    /// An adjustment to the [hue], in radians.
451    ///
452    /// Adjusting this value changes the perceived colors in the image: red to
453    /// yellow to green to blue, etc. It has no effect on the saturation or
454    /// brightness of the colors.
455    ///
456    /// [hue]: https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation
457    pub hue: f32,
458
459    /// Saturation adjustment applied after tonemapping.
460    /// Values below 1.0 desaturate, with a value of 0.0 resulting in a grayscale image
461    /// with luminance defined by ITU-R BT.709
462    /// Values above 1.0 increase saturation.
463    pub post_saturation: f32,
464
465    /// The luminance (brightness) ranges that are considered part of the
466    /// "midtones" of the image.
467    ///
468    /// This affects which [`ColorGradingSection`]s apply to which colors. Note
469    /// that the sections smoothly blend into one another, to avoid abrupt
470    /// transitions.
471    ///
472    /// The default value is 0.2 to 0.7.
473    pub midtones_range: Range<f32>,
474}
475
476/// The [`ColorGrading`] structure, packed into the most efficient form for the
477/// GPU.
478#[derive(#[automatically_derived]
impl ::core::clone::Clone for ColorGradingUniform {
    #[inline]
    fn clone(&self) -> ColorGradingUniform {
        let _: ::core::clone::AssertParamIsClone<Mat3>;
        let _: ::core::clone::AssertParamIsClone<Vec3>;
        let _: ::core::clone::AssertParamIsClone<Vec2>;
        let _: ::core::clone::AssertParamIsClone<f32>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for ColorGradingUniform { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for ColorGradingUniform {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["balance", "saturation", "contrast", "gamma", "gain", "lift",
                        "midtone_range", "exposure", "hue", "post_saturation"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.balance, &self.saturation, &self.contrast, &self.gamma,
                        &self.gain, &self.lift, &self.midtone_range, &self.exposure,
                        &self.hue, &&self.post_saturation];
        ::core::fmt::Formatter::debug_struct_fields_finish(f,
            "ColorGradingUniform", names, values)
    }
}Debug, impl encase::private::ShaderSize for ColorGradingUniform where
    Mat3: encase::private::ShaderSize, Vec3: encase::private::ShaderSize,
    Vec3: encase::private::ShaderSize, Vec3: encase::private::ShaderSize,
    Vec3: encase::private::ShaderSize, Vec3: encase::private::ShaderSize,
    Vec2: encase::private::ShaderSize, f32: encase::private::ShaderSize,
    f32: encase::private::ShaderSize, f32: encase::private::ShaderSize {}ShaderType)]
479pub struct ColorGradingUniform {
480    pub balance: Mat3,
481    pub saturation: Vec3,
482    pub contrast: Vec3,
483    pub gamma: Vec3,
484    pub gain: Vec3,
485    pub lift: Vec3,
486    pub midtone_range: Vec2,
487    pub exposure: f32,
488    pub hue: f32,
489    pub post_saturation: f32,
490}
491
492/// A section of color grading values that can be selectively applied to
493/// shadows, midtones, and highlights.
494#[derive(const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for ColorGradingSection where
            {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <f32 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for ColorGradingSection where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<f32>("saturation"),
                                                bevy_reflect::NamedField::new::<f32>("contrast"),
                                                bevy_reflect::NamedField::new::<f32>("gamma"),
                                                bevy_reflect::NamedField::new::<f32>("gain"),
                                                bevy_reflect::NamedField::new::<f32>("lift")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for ColorGradingSection where  {
            fn type_path() -> &'static str {
                "bevy_render::view::ColorGradingSection"
            }
            fn short_type_path() -> &'static str { "ColorGradingSection" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("ColorGradingSection")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_render::view".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_render::view")
            }
        }
        impl bevy_reflect::Reflect for ColorGradingSection 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(())
            }
        }
        impl bevy_reflect::func::args::GetOwnership for ColorGradingSection
            where  {
            fn ownership() -> bevy_reflect::func::args::Ownership {
                bevy_reflect::func::args::Ownership::Owned
            }
        }
        impl bevy_reflect::func::args::FromArg for ColorGradingSection where
            {
            type This<'from_arg> = ColorGradingSection;
            fn from_arg(arg: bevy_reflect::func::args::Arg)
                ->
                    ::core::result::Result<Self::This<'_>,
                    bevy_reflect::func::args::ArgError> {
                arg.take_owned()
            }
        }
        impl bevy_reflect::func::IntoReturn for ColorGradingSection where  {
            fn into_return<'into_return>(self)
                -> bevy_reflect::func::Return<'into_return> where
                Self: 'into_return {
                bevy_reflect::func::Return::Owned(bevy_reflect::__macro_exports::alloc_utils::Box::new(self))
            }
        }
        #[allow(non_upper_case_globals)]
        const _: () =
            {
                static __INVENTORY: ::inventory::Node =
                    ::inventory::Node {
                        value: &{
                                bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<ColorGradingSection
                                        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 ColorGradingSection where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "saturation" =>
                        ::core::option::Option::Some(&self.saturation),
                    "contrast" => ::core::option::Option::Some(&self.contrast),
                    "gamma" => ::core::option::Option::Some(&self.gamma),
                    "gain" => ::core::option::Option::Some(&self.gain),
                    "lift" => ::core::option::Option::Some(&self.lift),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "saturation" =>
                        ::core::option::Option::Some(&mut self.saturation),
                    "contrast" =>
                        ::core::option::Option::Some(&mut self.contrast),
                    "gamma" => ::core::option::Option::Some(&mut self.gamma),
                    "gain" => ::core::option::Option::Some(&mut self.gain),
                    "lift" => ::core::option::Option::Some(&mut self.lift),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&self.saturation),
                    1usize => ::core::option::Option::Some(&self.contrast),
                    2usize => ::core::option::Option::Some(&self.gamma),
                    3usize => ::core::option::Option::Some(&self.gain),
                    4usize => ::core::option::Option::Some(&self.lift),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize =>
                        ::core::option::Option::Some(&mut self.saturation),
                    1usize => ::core::option::Option::Some(&mut self.contrast),
                    2usize => ::core::option::Option::Some(&mut self.gamma),
                    3usize => ::core::option::Option::Some(&mut self.gain),
                    4usize => ::core::option::Option::Some(&mut self.lift),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("saturation"),
                    1usize => ::core::option::Option::Some("contrast"),
                    2usize => ::core::option::Option::Some("gamma"),
                    3usize => ::core::option::Option::Some("gain"),
                    4usize => ::core::option::Option::Some("lift"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "saturation" => ::core::option::Option::Some(0usize),
                    "contrast" => ::core::option::Option::Some(1usize),
                    "gamma" => ::core::option::Option::Some(2usize),
                    "gain" => ::core::option::Option::Some(3usize),
                    "lift" => ::core::option::Option::Some(4usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 5usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                -> bevy_reflect::structs::DynamicStruct {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("saturation",
                    bevy_reflect::PartialReflect::to_dynamic(&self.saturation));
                dynamic.insert_boxed("contrast",
                    bevy_reflect::PartialReflect::to_dynamic(&self.contrast));
                dynamic.insert_boxed("gamma",
                    bevy_reflect::PartialReflect::to_dynamic(&self.gamma));
                dynamic.insert_boxed("gain",
                    bevy_reflect::PartialReflect::to_dynamic(&self.gain));
                dynamic.insert_boxed("lift",
                    bevy_reflect::PartialReflect::to_dynamic(&self.lift));
                dynamic
            }
        }
        impl bevy_reflect::PartialReflect for ColorGradingSection 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> {
                let value =
                    <dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
                if let ::core::option::Option::Some(value) = value {
                    ::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
                            value))
                } else { ::core::option::Option::Some(false) }
            }
            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]
            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(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for ColorGradingSection 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 {
                            saturation: <f32 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "saturation")?)?,
                            contrast: <f32 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "contrast")?)?,
                            gamma: <f32 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "gamma")?)?,
                            gain: <f32 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "gain")?)?,
                            lift: <f32 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "lift")?)?,
                        };
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect, #[automatically_derived]
impl ::core::fmt::Debug for ColorGradingSection {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field5_finish(f,
            "ColorGradingSection", "saturation", &self.saturation, "contrast",
            &self.contrast, "gamma", &self.gamma, "gain", &self.gain, "lift",
            &&self.lift)
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for ColorGradingSection { }Copy, #[automatically_derived]
impl ::core::clone::Clone for ColorGradingSection {
    #[inline]
    fn clone(&self) -> ColorGradingSection {
        let _: ::core::clone::AssertParamIsClone<f32>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for ColorGradingSection {
    #[inline]
    fn eq(&self, other: &ColorGradingSection) -> bool {
        self.saturation == other.saturation && self.contrast == other.contrast
                    && self.gamma == other.gamma && self.gain == other.gain &&
            self.lift == other.lift
    }
}PartialEq)]
495#[reflect(Clone, PartialEq)]
496pub struct ColorGradingSection {
497    /// Values below 1.0 desaturate, with a value of 0.0 resulting in a grayscale image
498    /// with luminance defined by ITU-R BT.709.
499    /// Values above 1.0 increase saturation.
500    pub saturation: f32,
501
502    /// Adjusts the range of colors.
503    ///
504    /// A value of 1.0 applies no changes. Values below 1.0 move the colors more
505    /// toward a neutral gray. Values above 1.0 spread the colors out away from
506    /// the neutral gray.
507    pub contrast: f32,
508
509    /// A nonlinear luminance adjustment, mainly affecting the high end of the
510    /// range.
511    ///
512    /// This is the *n* exponent in the standard [ASC CDL] formula for color
513    /// correction:
514    ///
515    /// ```text
516    /// out = (i × s + o)ⁿ
517    /// ```
518    ///
519    /// [ASC CDL]: https://en.wikipedia.org/wiki/ASC_CDL#Combined_Function
520    pub gamma: f32,
521
522    /// A linear luminance adjustment, mainly affecting the middle part of the
523    /// range.
524    ///
525    /// This is the *s* factor in the standard [ASC CDL] formula for color
526    /// correction:
527    ///
528    /// ```text
529    /// out = (i × s + o)ⁿ
530    /// ```
531    ///
532    /// [ASC CDL]: https://en.wikipedia.org/wiki/ASC_CDL#Combined_Function
533    pub gain: f32,
534
535    /// A fixed luminance adjustment, mainly affecting the lower part of the
536    /// range.
537    ///
538    /// This is the *o* term in the standard [ASC CDL] formula for color
539    /// correction:
540    ///
541    /// ```text
542    /// out = (i × s + o)ⁿ
543    /// ```
544    ///
545    /// [ASC CDL]: https://en.wikipedia.org/wiki/ASC_CDL#Combined_Function
546    pub lift: f32,
547}
548
549impl Default for ColorGradingGlobal {
550    fn default() -> Self {
551        Self {
552            exposure: 0.0,
553            temperature: 0.0,
554            tint: 0.0,
555            hue: 0.0,
556            post_saturation: 1.0,
557            midtones_range: 0.2..0.7,
558        }
559    }
560}
561
562impl Default for ColorGradingSection {
563    fn default() -> Self {
564        Self {
565            saturation: 1.0,
566            contrast: 1.0,
567            gamma: 1.0,
568            gain: 1.0,
569            lift: 0.0,
570        }
571    }
572}
573
574impl ColorGrading {
575    /// Creates a new [`ColorGrading`] instance in which shadows, midtones, and
576    /// highlights all have the same set of color grading values.
577    pub fn with_identical_sections(
578        global: ColorGradingGlobal,
579        section: ColorGradingSection,
580    ) -> ColorGrading {
581        ColorGrading {
582            global,
583            highlights: section,
584            midtones: section,
585            shadows: section,
586        }
587    }
588
589    /// Returns an iterator that visits the shadows, midtones, and highlights
590    /// sections, in that order.
591    pub fn all_sections(&self) -> impl Iterator<Item = &ColorGradingSection> {
592        [&self.shadows, &self.midtones, &self.highlights].into_iter()
593    }
594
595    /// Applies the given mutating function to the shadows, midtones, and
596    /// highlights sections, in that order.
597    ///
598    /// Returns an array composed of the results of such evaluation, in that
599    /// order.
600    pub fn all_sections_mut(&mut self) -> impl Iterator<Item = &mut ColorGradingSection> {
601        [&mut self.shadows, &mut self.midtones, &mut self.highlights].into_iter()
602    }
603}
604
605/// A resource, part of the render world, that stores the resolved origin for
606/// LOD selection for shadow maps of point and spot lights.
607#[derive(#[automatically_derived]
impl ::core::default::Default for RenderShadowLodOrigin {
    #[inline]
    fn default() -> RenderShadowLodOrigin {
        RenderShadowLodOrigin(::core::default::Default::default())
    }
}Default, impl bevy_ecs::resource::Resource for RenderShadowLodOrigin where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, #[automatically_derived]
impl ::core::fmt::Debug for RenderShadowLodOrigin {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f,
            "RenderShadowLodOrigin", &&self.0)
    }
}Debug)]
608pub struct RenderShadowLodOrigin(pub Vec3);
609
610#[derive(#[automatically_derived]
impl ::core::clone::Clone for ViewUniform {
    #[inline]
    fn clone(&self) -> ViewUniform {
        ViewUniform {
            clip_from_world: ::core::clone::Clone::clone(&self.clip_from_world),
            unjittered_clip_from_world: ::core::clone::Clone::clone(&self.unjittered_clip_from_world),
            world_from_clip: ::core::clone::Clone::clone(&self.world_from_clip),
            world_from_view: ::core::clone::Clone::clone(&self.world_from_view),
            view_from_world: ::core::clone::Clone::clone(&self.view_from_world),
            clip_from_view: ::core::clone::Clone::clone(&self.clip_from_view),
            view_from_clip: ::core::clone::Clone::clone(&self.view_from_clip),
            world_position: ::core::clone::Clone::clone(&self.world_position),
            exposure: ::core::clone::Clone::clone(&self.exposure),
            viewport: ::core::clone::Clone::clone(&self.viewport),
            main_pass_viewport: ::core::clone::Clone::clone(&self.main_pass_viewport),
            frustum: ::core::clone::Clone::clone(&self.frustum),
            lod_view_world_position: ::core::clone::Clone::clone(&self.lod_view_world_position),
            color_grading: ::core::clone::Clone::clone(&self.color_grading),
            mip_bias: ::core::clone::Clone::clone(&self.mip_bias),
            frame_count: ::core::clone::Clone::clone(&self.frame_count),
        }
    }
}Clone, impl encase::private::ShaderSize for ViewUniform where
    Mat4: encase::private::ShaderSize, Mat4: encase::private::ShaderSize,
    Mat4: encase::private::ShaderSize, Mat4: encase::private::ShaderSize,
    Mat4: encase::private::ShaderSize, Mat4: encase::private::ShaderSize,
    Mat4: encase::private::ShaderSize, Vec3: encase::private::ShaderSize,
    f32: encase::private::ShaderSize, Vec4: encase::private::ShaderSize,
    Vec4: encase::private::ShaderSize, [Vec4; 6]: encase::private::ShaderSize,
    Vec3: encase::private::ShaderSize,
    ColorGradingUniform: encase::private::ShaderSize,
    f32: encase::private::ShaderSize, u32: encase::private::ShaderSize {}ShaderType)]
611pub struct ViewUniform {
612    pub clip_from_world: Mat4,
613    pub unjittered_clip_from_world: Mat4,
614    pub world_from_clip: Mat4,
615    pub world_from_view: Mat4,
616    pub view_from_world: Mat4,
617    /// Typically a column-major right-handed projection matrix, one of either:
618    ///
619    /// Perspective (infinite reverse z)
620    /// ```text
621    /// f = 1 / tan(fov_y_radians / 2)
622    ///
623    /// ⎡ f / aspect  0   0     0 ⎤
624    /// ⎢          0  f   0     0 ⎥
625    /// ⎢          0  0   0  near ⎥
626    /// ⎣          0  0  -1     0 ⎦
627    /// ```
628    ///
629    /// Orthographic
630    /// ```text
631    /// w = right - left
632    /// h = top - bottom
633    /// d = far - near
634    /// cw = -right - left
635    /// ch = -top - bottom
636    ///
637    /// ⎡ 2 / w      0      0   cw / w ⎤
638    /// ⎢     0  2 / h      0   ch / h ⎥
639    /// ⎢     0      0  1 / d  far / d ⎥
640    /// ⎣     0      0      0        1 ⎦
641    /// ```
642    ///
643    /// `clip_from_view[3][3] == 1.0` is the standard way to check if a projection is orthographic
644    ///
645    /// Glam matrices are column major, so for example getting the near plane of a perspective projection is `clip_from_view[3][2]`
646    ///
647    /// Custom projections are also possible however.
648    pub clip_from_view: Mat4,
649    pub view_from_clip: Mat4,
650    pub world_position: Vec3,
651    pub exposure: f32,
652    // viewport(x_origin, y_origin, width, height)
653    pub viewport: Vec4,
654    pub main_pass_viewport: Vec4,
655    /// 6 world-space half spaces (normal: vec3, distance: f32) ordered left, right, top, bottom, near, far.
656    /// The normal vectors point towards the interior of the frustum.
657    /// A half space contains `p` if `normal.dot(p) + distance > 0.`
658    pub frustum: [Vec4; 6],
659    /// The world-space position of the camera used to resolve visibility
660    /// ranges.
661    ///
662    /// This is the position of the camera itself, unless this view isn't
663    /// associated with a camera, in which case it's the position of the primary
664    /// camera.
665    pub lod_view_world_position: Vec3,
666    pub color_grading: ColorGradingUniform,
667    pub mip_bias: f32,
668    pub frame_count: u32,
669}
670
671#[derive(impl bevy_ecs::resource::Resource for ViewUniforms where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource)]
672pub struct ViewUniforms {
673    pub uniforms: DynamicUniformBuffer<ViewUniform>,
674}
675
676impl FromWorld for ViewUniforms {
677    fn from_world(world: &mut World) -> Self {
678        let mut uniforms = DynamicUniformBuffer::default();
679        uniforms.set_label(Some("view_uniforms_buffer"));
680
681        let render_device = world.resource::<RenderDevice>();
682        if render_device.limits().max_storage_buffers_per_shader_stage > 0 {
683            uniforms.add_usages(BufferUsages::STORAGE);
684        }
685
686        Self { uniforms }
687    }
688}
689
690#[derive(impl bevy_ecs::component::Component for ViewUniformOffset 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) {}
    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)]
691pub struct ViewUniformOffset {
692    pub offset: u32,
693}
694
695#[derive(impl bevy_ecs::component::Component for ViewTarget 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) {}
    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, #[automatically_derived]
impl ::core::clone::Clone for ViewTarget {
    #[inline]
    fn clone(&self) -> ViewTarget {
        ViewTarget {
            main_textures: ::core::clone::Clone::clone(&self.main_textures),
            main_texture_format: ::core::clone::Clone::clone(&self.main_texture_format),
            main_texture: ::core::clone::Clone::clone(&self.main_texture),
            out_texture: ::core::clone::Clone::clone(&self.out_texture),
            compositing_space: ::core::clone::Clone::clone(&self.compositing_space),
        }
    }
}Clone)]
696pub struct ViewTarget {
697    main_textures: MainTargetTextures,
698    main_texture_format: TextureFormat,
699    /// 0 represents `main_textures.a`, 1 represents `main_textures.b`
700    /// This is shared across view targets with the same render target
701    main_texture: Arc<AtomicUsize>,
702    /// The final output attachment this view will present to, if available.
703    out_texture: Option<OutputColorAttachment>,
704    /// Color space of values stored in the main texture (for blit conversion to output)
705    pub compositing_space: Option<CompositingSpace>,
706}
707
708/// Contains [`OutputColorAttachment`] used for each target present on any view in the current
709/// frame, after being prepared by [`prepare_view_attachments`]. Users that want to override
710/// the default output color attachment for a specific target can do so by adding a
711/// [`OutputColorAttachment`] to this resource before [`prepare_view_targets`] is called.
712#[derive(impl bevy_ecs::resource::Resource for ViewTargetAttachments where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, #[automatically_derived]
impl ::core::default::Default for ViewTargetAttachments {
    #[inline]
    fn default() -> ViewTargetAttachments {
        ViewTargetAttachments(::core::default::Default::default())
    }
}Default, impl ::core::ops::Deref for ViewTargetAttachments {
    type Target = HashMap<NormalizedRenderTarget, OutputColorAttachment>;
    fn deref(&self) -> &Self::Target { &self.0 }
}Deref, impl ::core::ops::DerefMut for ViewTargetAttachments {
    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}DerefMut)]
713pub struct ViewTargetAttachments(HashMap<NormalizedRenderTarget, OutputColorAttachment>);
714
715pub struct PostProcessWrite<'a> {
716    pub source: &'a TextureView,
717    pub source_texture: &'a Texture,
718    pub destination: &'a TextureView,
719    pub destination_texture: &'a Texture,
720}
721
722impl From<ColorGrading> for ColorGradingUniform {
723    fn from(component: ColorGrading) -> Self {
724        // Compute the balance matrix that will be used to apply the white
725        // balance adjustment to an RGB color. Our general approach will be to
726        // convert both the color and the developer-supplied white point to the
727        // LMS color space, apply the conversion, and then convert back.
728        //
729        // First, we start with the CIE 1931 *xy* values of the standard D65
730        // illuminant:
731        // <https://en.wikipedia.org/wiki/Standard_illuminant#D65_values>
732        //
733        // We then adjust them based on the developer's requested white balance.
734        let white_point_xy = D65_XY + vec2(-component.global.temperature, component.global.tint);
735
736        // Convert the white point from CIE 1931 *xy* to LMS. First, we convert to XYZ:
737        //
738        //                  Y          Y
739        //     Y = 1    X = ─ x    Z = ─ (1 - x - y)
740        //                  y          y
741        //
742        // Then we convert from XYZ to LMS color space, using the CAM16 matrix
743        // from <https://en.wikipedia.org/wiki/LMS_color_space#Later_CIECAMs>:
744        //
745        //     ⎡ L ⎤   ⎡  0.401   0.650  -0.051 ⎤ ⎡ X ⎤
746        //     ⎢ M ⎥ = ⎢ -0.250   1.204   0.046 ⎥ ⎢ Y ⎥
747        //     ⎣ S ⎦   ⎣ -0.002   0.049   0.953 ⎦ ⎣ Z ⎦
748        //
749        // The following formula is just a simplification of the above.
750
751        let white_point_lms = vec3(0.701634, 1.15856, -0.904175)
752            + (vec3(-0.051461, 0.045854, 0.953127)
753                + vec3(0.452749, -0.296122, -0.955206) * white_point_xy.x)
754                / white_point_xy.y;
755
756        // Now that we're in LMS space, perform the white point scaling.
757        let white_point_adjustment = Mat3::from_diagonal(D65_LMS / white_point_lms);
758
759        // Finally, combine the RGB → LMS → corrected LMS → corrected RGB
760        // pipeline into a single 3×3 matrix.
761        let balance = LMS_TO_RGB * white_point_adjustment * RGB_TO_LMS;
762
763        Self {
764            balance,
765            saturation: vec3(
766                component.shadows.saturation,
767                component.midtones.saturation,
768                component.highlights.saturation,
769            ),
770            contrast: vec3(
771                component.shadows.contrast,
772                component.midtones.contrast,
773                component.highlights.contrast,
774            ),
775            gamma: vec3(
776                component.shadows.gamma,
777                component.midtones.gamma,
778                component.highlights.gamma,
779            ),
780            gain: vec3(
781                component.shadows.gain,
782                component.midtones.gain,
783                component.highlights.gain,
784            ),
785            lift: vec3(
786                component.shadows.lift,
787                component.midtones.lift,
788                component.highlights.lift,
789            ),
790            midtone_range: vec2(
791                component.global.midtones_range.start,
792                component.global.midtones_range.end,
793            ),
794            exposure: component.global.exposure,
795            hue: component.global.hue,
796            post_saturation: component.global.post_saturation,
797        }
798    }
799}
800
801/// Add this component to a camera to disable *indirect mode*.
802///
803/// Indirect mode, automatically enabled on supported hardware, allows Bevy to
804/// offload transform and cull operations to the GPU, reducing CPU overhead.
805/// Doing this, however, reduces the amount of control that your app has over
806/// instancing decisions. In certain circumstances, you may want to disable
807/// indirect drawing so that your app can manually instance meshes as it sees
808/// fit. See the `custom_shader_instancing` example.
809///
810/// The vast majority of applications will not need to use this component, as it
811/// generally reduces rendering performance.
812///
813/// Note: This component should only be added when initially spawning a camera. Adding
814/// or removing after spawn can result in unspecified behavior.
815#[derive(impl bevy_ecs::component::Component for NoIndirectDrawing 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) {}
    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, #[automatically_derived]
impl ::core::default::Default for NoIndirectDrawing {
    #[inline]
    fn default() -> NoIndirectDrawing { NoIndirectDrawing {} }
}Default)]
816pub struct NoIndirectDrawing;
817
818impl ViewTarget {
819    #[deprecated(
820        note = "Use ExtractedView::target_format where possible. Bevy does not encourage a default HDR TextureFormat anymore. If you really need this, use TextureFormat::Rgba16Float"
821    )]
822    pub const TEXTURE_FORMAT_HDR: TextureFormat = TextureFormat::Rgba16Float;
823
824    /// Retrieve this target's main texture's color attachment.
825    pub fn get_color_attachment(&self) -> RenderPassColorAttachment<'_> {
826        if self.main_texture.load(Ordering::SeqCst) == 0 {
827            self.main_textures.a.get_attachment()
828        } else {
829            self.main_textures.b.get_attachment()
830        }
831    }
832
833    /// Retrieve this target's "unsampled" main texture's color attachment.
834    pub fn get_unsampled_color_attachment(&self) -> RenderPassColorAttachment<'_> {
835        if self.main_texture.load(Ordering::SeqCst) == 0 {
836            self.main_textures.a.get_unsampled_attachment()
837        } else {
838            self.main_textures.b.get_unsampled_attachment()
839        }
840    }
841
842    /// The "main" unsampled texture.
843    pub fn main_texture(&self) -> &Texture {
844        if self.main_texture.load(Ordering::SeqCst) == 0 {
845            &self.main_textures.a.texture.texture
846        } else {
847            &self.main_textures.b.texture.texture
848        }
849    }
850
851    /// The _other_ "main" unsampled texture.
852    /// In most cases you should use [`Self::main_texture`] instead and never this.
853    /// The textures will naturally be swapped when [`Self::post_process_write`] is called.
854    ///
855    /// A use case for this is to be able to prepare a bind group for all main textures
856    /// ahead of time.
857    pub fn main_texture_other(&self) -> &Texture {
858        if self.main_texture.load(Ordering::SeqCst) == 0 {
859            &self.main_textures.b.texture.texture
860        } else {
861            &self.main_textures.a.texture.texture
862        }
863    }
864
865    /// The "main" unsampled texture.
866    pub fn main_texture_view(&self) -> &TextureView {
867        if self.main_texture.load(Ordering::SeqCst) == 0 {
868            &self.main_textures.a.texture.default_view
869        } else {
870            &self.main_textures.b.texture.default_view
871        }
872    }
873
874    /// The _other_ "main" unsampled texture view.
875    /// In most cases you should use [`Self::main_texture_view`] instead and never this.
876    /// The textures will naturally be swapped when [`Self::post_process_write`] is called.
877    ///
878    /// A use case for this is to be able to prepare a bind group for all main textures
879    /// ahead of time.
880    pub fn main_texture_other_view(&self) -> &TextureView {
881        if self.main_texture.load(Ordering::SeqCst) == 0 {
882            &self.main_textures.b.texture.default_view
883        } else {
884            &self.main_textures.a.texture.default_view
885        }
886    }
887
888    /// The "main" sampled texture.
889    pub fn sampled_main_texture(&self) -> Option<&Texture> {
890        self.main_textures
891            .a
892            .resolve_target
893            .as_ref()
894            .map(|sampled| &sampled.texture)
895    }
896
897    /// The "main" sampled texture view.
898    pub fn sampled_main_texture_view(&self) -> Option<&TextureView> {
899        self.main_textures
900            .a
901            .resolve_target
902            .as_ref()
903            .map(|sampled| &sampled.default_view)
904    }
905
906    /// Currently bevy's main texture format can be:
907    /// - If rendering to screen:
908    ///   For HDR, it's `Rgba16Float`.
909    ///   For LDR, it's `Rgba8Unorm` when [`CompositingSpace::Srgb`], otherwise `Rgba8UnormSrgb`.
910    /// - If rendering to texture: the format is the same as texture view's format.
911    #[inline]
912    pub fn main_texture_format(&self) -> TextureFormat {
913        self.main_texture_format
914    }
915
916    /// The final texture this view will render to.
917    #[inline]
918    pub fn out_texture(&self) -> Option<&TextureView> {
919        self.out_texture.as_ref().map(|t| &t.view)
920    }
921
922    /// The final texture this view will render to, as a color attachment.
923    pub fn out_texture_color_attachment(
924        &self,
925        clear_color: Option<LinearRgba>,
926    ) -> Option<RenderPassColorAttachment<'_>> {
927        self.out_texture
928            .as_ref()
929            .map(|t| t.get_attachment(clear_color))
930    }
931
932    /// Whether the final texture this view will render to needs to be presented.
933    pub fn needs_present(&self) -> bool {
934        self.out_texture
935            .as_ref()
936            .is_some_and(OutputColorAttachment::needs_present)
937    }
938
939    /// The format of the final texture this view will render to, if any.
940    #[inline]
941    pub fn out_texture_view_format(&self) -> Option<TextureFormat> {
942        self.out_texture.as_ref().map(|t| t.view_format)
943    }
944
945    /// This will start a new "post process write", which assumes that the caller
946    /// will write the [`PostProcessWrite`]'s `source` to the `destination`.
947    ///
948    /// `source` is the "current" main texture. This will internally flip this
949    /// [`ViewTarget`]'s main texture to the `destination` texture, so the caller
950    /// _must_ ensure `source` is copied to `destination`, with or without modifications.
951    /// Failing to do so will cause the current main texture information to be lost.
952    pub fn post_process_write(&self) -> PostProcessWrite<'_> {
953        let old_is_a_main_texture = self.main_texture.fetch_xor(1, Ordering::SeqCst);
954        // if the old main texture is a, then the post processing must write from a to b
955        if old_is_a_main_texture == 0 {
956            self.main_textures.b.mark_as_cleared();
957            PostProcessWrite {
958                source: &self.main_textures.a.texture.default_view,
959                source_texture: &self.main_textures.a.texture.texture,
960                destination: &self.main_textures.b.texture.default_view,
961                destination_texture: &self.main_textures.b.texture.texture,
962            }
963        } else {
964            self.main_textures.a.mark_as_cleared();
965            PostProcessWrite {
966                source: &self.main_textures.b.texture.default_view,
967                source_texture: &self.main_textures.b.texture.texture,
968                destination: &self.main_textures.a.texture.default_view,
969                destination_texture: &self.main_textures.a.texture.texture,
970            }
971        }
972    }
973}
974
975#[derive(impl bevy_ecs::component::Component for ViewDepthTexture 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) {}
    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)]
976pub struct ViewDepthTexture {
977    pub texture: Texture,
978    attachment: DepthAttachment,
979}
980
981impl ViewDepthTexture {
982    pub fn new(texture: CachedTexture, clear_value: Option<f32>) -> Self {
983        Self {
984            texture: texture.texture,
985            attachment: DepthAttachment::new(texture.default_view, clear_value),
986        }
987    }
988
989    pub fn get_attachment(&self, store: StoreOp) -> RenderPassDepthStencilAttachment<'_> {
990        self.attachment.get_attachment(store)
991    }
992
993    pub fn view(&self) -> &TextureView {
994        &self.attachment.view
995    }
996}
997
998pub fn prepare_view_uniforms(
999    mut commands: Commands,
1000    render_device: Res<RenderDevice>,
1001    render_queue: Res<RenderQueue>,
1002    mut view_uniforms: ResMut<ViewUniforms>,
1003    views: Query<(
1004        Entity,
1005        Option<&ExtractedCamera>,
1006        &ExtractedView,
1007        Option<&Frustum>,
1008        Option<&TemporalJitter>,
1009        Option<&MipBias>,
1010        Option<&MainPassResolutionOverride>,
1011    )>,
1012    frame_count: Res<FrameCount>,
1013    shadow_lod_origin: Option<Res<RenderShadowLodOrigin>>,
1014) {
1015    let view_iter = views.iter();
1016    let view_count = view_iter.len();
1017    let Some(mut writer) =
1018        view_uniforms
1019            .uniforms
1020            .get_writer(view_count, &render_device, &render_queue)
1021    else {
1022        return;
1023    };
1024    for (
1025        entity,
1026        extracted_camera,
1027        extracted_view,
1028        frustum,
1029        temporal_jitter,
1030        mip_bias,
1031        resolution_override,
1032    ) in &views
1033    {
1034        let viewport = extracted_view.viewport.as_vec4();
1035        let mut main_pass_viewport = viewport;
1036        if let Some(resolution_override) = resolution_override {
1037            main_pass_viewport.z = resolution_override.0.x as f32;
1038            main_pass_viewport.w = resolution_override.0.y as f32;
1039        }
1040
1041        let unjittered_projection = extracted_view.clip_from_view;
1042        let mut clip_from_view = unjittered_projection;
1043
1044        if let Some(temporal_jitter) = temporal_jitter {
1045            temporal_jitter.jitter_projection(&mut clip_from_view, main_pass_viewport.zw());
1046        }
1047
1048        let view_from_clip = clip_from_view.inverse();
1049        let world_from_view = extracted_view.world_from_view.to_matrix();
1050        let view_from_world = world_from_view.inverse();
1051
1052        let clip_from_world = if temporal_jitter.is_some() {
1053            clip_from_view * view_from_world
1054        } else {
1055            extracted_view
1056                .clip_from_world
1057                .unwrap_or_else(|| clip_from_view * view_from_world)
1058        };
1059
1060        // Map Frustum type to shader array<vec4<f32>, 6>
1061        let frustum = frustum
1062            .map(|frustum| frustum.half_spaces.map(|h| h.normal_d()))
1063            .unwrap_or([Vec4::ZERO; 6]);
1064
1065        // Determine the position of the camera used for resolving visibility
1066        // ranges (LODs).
1067        let lod_view_world_position = match (&extracted_camera, &shadow_lod_origin) {
1068            (Some(_), _) | (None, None) => {
1069                // If we're rendering a camera directly (i.e. we're not
1070                // rendering a shadow map), we use this camera's position as the
1071                // LOD view position.
1072                extracted_view.world_from_view.translation()
1073            }
1074            (None, Some(shadow_lod_origin))
1075                if extracted_view.retained_view_entity.auxiliary_entity
1076                    == MainEntity::from(Entity::PLACEHOLDER) =>
1077            {
1078                // If this is a shadow map not associated with a camera (a point
1079                // light or spot light shadow map), use the shadow LOD origin.
1080                shadow_lod_origin.0
1081            }
1082            (None, Some(shadow_lod_origin)) => {
1083                // Otherwise, if we're rendering a shadow map that is associated
1084                // with a camera (i.e. a directional light shadow map, at
1085                // present), we use the position of that camera as the LOD view
1086                // position. This ensures that each rendered object has a shadow
1087                // and that no invisible objects have shadows.
1088                match views.get(
1089                    extracted_view
1090                        .retained_view_entity
1091                        .auxiliary_entity
1092                        .entity(),
1093                ) {
1094                    Ok((_, _, camera_view, _, _, _, _)) => {
1095                        camera_view.world_from_view.translation()
1096                    }
1097                    Err(_) => shadow_lod_origin.0,
1098                }
1099            }
1100        };
1101
1102        let view_uniforms = ViewUniformOffset {
1103            offset: writer.write(&ViewUniform {
1104                clip_from_world,
1105                unjittered_clip_from_world: unjittered_projection * view_from_world,
1106                world_from_clip: world_from_view * view_from_clip,
1107                world_from_view,
1108                view_from_world,
1109                clip_from_view,
1110                view_from_clip,
1111                world_position: extracted_view.world_from_view.translation(),
1112                exposure: extracted_camera
1113                    .map(|c| c.exposure)
1114                    .unwrap_or_else(|| Exposure::default().exposure()),
1115                viewport,
1116                main_pass_viewport,
1117                frustum,
1118                lod_view_world_position,
1119                color_grading: extracted_view.color_grading.clone().into(),
1120                mip_bias: mip_bias.unwrap_or(&MipBias(0.0)).0,
1121                frame_count: frame_count.0,
1122            }),
1123        };
1124
1125        commands.entity(entity).insert(view_uniforms);
1126    }
1127}
1128
1129#[derive(#[automatically_derived]
impl ::core::clone::Clone for MainTargetTextures {
    #[inline]
    fn clone(&self) -> MainTargetTextures {
        MainTargetTextures {
            a: ::core::clone::Clone::clone(&self.a),
            b: ::core::clone::Clone::clone(&self.b),
            main_texture: ::core::clone::Clone::clone(&self.main_texture),
        }
    }
}Clone)]
1130struct MainTargetTextures {
1131    a: ColorAttachment,
1132    b: ColorAttachment,
1133    /// 0 represents `main_textures.a`, 1 represents `main_textures.b`
1134    /// This is shared across view targets with the same render target
1135    main_texture: Arc<AtomicUsize>,
1136}
1137
1138/// Prepares the view target [`OutputColorAttachment`] for each view in the current frame.
1139pub fn prepare_view_attachments(
1140    windows: Res<ExtractedWindows>,
1141    images: Res<RenderAssets<GpuImage>>,
1142    manual_texture_views: Res<ManualTextureViews>,
1143    cameras: Query<&ExtractedCamera>,
1144    mut view_target_attachments: ResMut<ViewTargetAttachments>,
1145) {
1146    for camera in cameras.iter() {
1147        let Some(target) = &camera.target else {
1148            continue;
1149        };
1150
1151        if #[allow(non_exhaustive_omitted_patterns)] match camera.output_mode {
    bevy_camera::CameraOutputMode::Skip => true,
    _ => false,
}matches!(camera.output_mode, bevy_camera::CameraOutputMode::Skip) {
1152            continue;
1153        }
1154
1155        match view_target_attachments.entry(target.clone()) {
1156            Entry::Occupied(_) => {}
1157            Entry::Vacant(entry) => {
1158                let Some(attachment) = target
1159                    .get_texture_view(&windows, &images, &manual_texture_views)
1160                    .cloned()
1161                    .zip(target.get_texture_view_format(&windows, &images, &manual_texture_views))
1162                    .map(|(view, format)| OutputColorAttachment::new(view.clone(), format))
1163                else {
1164                    continue;
1165                };
1166                entry.insert(attachment);
1167            }
1168        };
1169    }
1170}
1171
1172/// Clears the view target [`OutputColorAttachment`]s.
1173pub fn clear_view_attachments(mut view_target_attachments: ResMut<ViewTargetAttachments>) {
1174    view_target_attachments.clear();
1175}
1176
1177pub fn cleanup_view_targets_for_resize(
1178    mut commands: Commands,
1179    windows: Res<ExtractedWindows>,
1180    cameras: Query<(Entity, &ExtractedCamera), With<ViewTarget>>,
1181) {
1182    for (entity, camera) in &cameras {
1183        if let Some(NormalizedRenderTarget::Window(window_ref)) = &camera.target
1184            && let Some(window) = windows.get(&window_ref.entity())
1185            && (window.size_changed || window.present_mode_changed)
1186        {
1187            commands.entity(entity).remove::<ViewTarget>();
1188        }
1189    }
1190}
1191
1192type MainTextureKey = (
1193    Option<NormalizedRenderTarget>,
1194    TextureUsages,
1195    TextureFormat,
1196    Msaa,
1197);
1198
1199pub fn prepare_view_targets(
1200    mut commands: Commands,
1201    clear_color_global: Res<ClearColor>,
1202    render_device: Res<RenderDevice>,
1203    mut texture_cache: ResMut<TextureCache>,
1204    cameras: Query<(
1205        Entity,
1206        &ExtractedCamera,
1207        &ExtractedView,
1208        &CameraMainTextureUsages,
1209        &Msaa,
1210    )>,
1211    view_target_attachments: Res<ViewTargetAttachments>,
1212    mut main_texture_atomics: Local<HashMap<MainTextureKey, Weak<AtomicUsize>>>,
1213) {
1214    main_texture_atomics.retain(|_, weak| weak.strong_count() > 0);
1215
1216    let mut textures = <HashMap<_, _>>::default();
1217    for (entity, camera, view, texture_usage, msaa) in cameras.iter() {
1218        let Some(target_size) = camera.physical_target_size else {
1219            // If we don't have a target size, we can't create the main texture and have to bail
1220            commands.entity(entity).try_remove::<ViewTarget>();
1221            continue;
1222        };
1223
1224        let out_attachment = camera
1225            .target
1226            .as_ref()
1227            .and_then(|target| view_target_attachments.get(target));
1228
1229        // If we have no output and the camera is set to clear, we can skip rendering
1230        // entirely.
1231        if out_attachment.is_none() && !#[allow(non_exhaustive_omitted_patterns)] match camera.clear_color {
    ClearColorConfig::None => true,
    _ => false,
}matches!(camera.clear_color, ClearColorConfig::None) {
1232            commands.entity(entity).try_remove::<ViewTarget>();
1233            continue;
1234        }
1235
1236        let main_texture_format = view.target_format;
1237
1238        let clear_color = match camera.clear_color {
1239            ClearColorConfig::Custom(color) => Some(color),
1240            ClearColorConfig::None => None,
1241            _ => Some(clear_color_global.0),
1242        };
1243
1244        // Convert clear color to the format expected by the main texture
1245        let converted_clear_color: Option<WgpuColor> =
1246            clear_color.map(|color| match camera.compositing_space {
1247                // If main texture stores Oklab or Srgb, convert Color to it for correct clear.
1248                Some(CompositingSpace::Oklab) => Oklaba::from(color).into(),
1249                Some(CompositingSpace::Srgb) => Srgba::from(color).into(),
1250                Some(CompositingSpace::Linear) | None => LinearRgba::from(color).into(),
1251            });
1252
1253        let key: MainTextureKey = (
1254            camera.target.clone(),
1255            texture_usage.0,
1256            main_texture_format,
1257            *msaa,
1258        );
1259        let (a, b, sampled, main_texture) = textures.entry(key.clone()).or_insert_with(|| {
1260            let descriptor = TextureDescriptor {
1261                label: None,
1262                size: target_size.to_extents(),
1263                mip_level_count: 1,
1264                sample_count: 1,
1265                dimension: TextureDimension::D2,
1266                format: main_texture_format,
1267                usage: texture_usage.0,
1268                view_formats: match main_texture_format {
1269                    TextureFormat::Bgra8Unorm => &[TextureFormat::Bgra8UnormSrgb],
1270                    TextureFormat::Rgba8Unorm => &[TextureFormat::Rgba8UnormSrgb],
1271                    _ => &[],
1272                },
1273            };
1274            let a = texture_cache.get(
1275                &render_device,
1276                TextureDescriptor {
1277                    label: Some("main_texture_a"),
1278                    ..descriptor
1279                },
1280            );
1281            let b = texture_cache.get(
1282                &render_device,
1283                TextureDescriptor {
1284                    label: Some("main_texture_b"),
1285                    ..descriptor
1286                },
1287            );
1288            let sampled = if msaa.samples() > 1 {
1289                let sampled = texture_cache.get(
1290                    &render_device,
1291                    TextureDescriptor {
1292                        label: Some("main_texture_sampled"),
1293                        size: target_size.to_extents(),
1294                        mip_level_count: 1,
1295                        sample_count: msaa.samples(),
1296                        dimension: TextureDimension::D2,
1297                        format: main_texture_format,
1298                        usage: TextureUsages::RENDER_ATTACHMENT,
1299                        view_formats: descriptor.view_formats,
1300                    },
1301                );
1302                Some(sampled)
1303            } else {
1304                None
1305            };
1306            // re-use the same atomics frame to frame for views with the same main texture
1307            // to ensure post process writes persist through msaa writeback
1308            let main_texture = match main_texture_atomics.entry(key) {
1309                Entry::Occupied(e) => e
1310                    .get()
1311                    .upgrade()
1312                    .expect("dead weaks were pruned at top of system"),
1313                Entry::Vacant(e) => {
1314                    let arc = Arc::new(AtomicUsize::new(0));
1315                    e.insert(Arc::downgrade(&arc));
1316                    arc
1317                }
1318            };
1319            (a, b, sampled, main_texture)
1320        });
1321
1322        let main_textures = MainTargetTextures {
1323            a: ColorAttachment::new(a.clone(), sampled.clone(), None, converted_clear_color),
1324            b: ColorAttachment::new(b.clone(), sampled.clone(), None, converted_clear_color),
1325            main_texture: main_texture.clone(),
1326        };
1327
1328        commands.entity(entity).insert(ViewTarget {
1329            main_texture: main_textures.main_texture.clone(),
1330            main_textures,
1331            main_texture_format,
1332            out_texture: out_attachment.cloned(),
1333            compositing_space: camera.compositing_space,
1334        });
1335    }
1336}