bevy_core_pipeline/prepass/
mod.rs1pub mod node;
29
30use core::ops::Range;
31
32use crate::deferred::{DEFERRED_LIGHTING_PASS_ID_FORMAT, DEFERRED_PREPASS_FORMAT};
33use bevy_asset::UntypedAssetId;
34use bevy_ecs::prelude::*;
35use bevy_math::Mat4;
36use bevy_reflect::{std_traits::ReflectDefault, Reflect};
37use bevy_render::mesh::allocator::SlabId;
38use bevy_render::render_phase::PhaseItemBatchSetKey;
39use bevy_render::sync_world::MainEntity;
40use bevy_render::{
41    render_phase::{
42        BinnedPhaseItem, CachedRenderPipelinePhaseItem, DrawFunctionId, PhaseItem,
43        PhaseItemExtraIndex,
44    },
45    render_resource::{
46        CachedRenderPipelineId, ColorTargetState, ColorWrites, DynamicUniformBuffer, Extent3d,
47        ShaderType, TextureFormat, TextureView,
48    },
49    texture::ColorAttachment,
50};
51
52pub const NORMAL_PREPASS_FORMAT: TextureFormat = TextureFormat::Rgb10a2Unorm;
53pub const MOTION_VECTOR_PREPASS_FORMAT: TextureFormat = TextureFormat::Rg16Float;
54
55#[derive(Component, Default, Reflect, Clone)]
57#[reflect(Component, Default, Clone)]
58pub struct DepthPrepass;
59
60#[derive(Component, Default, Reflect, Clone)]
63#[reflect(Component, Default, Clone)]
64pub struct NormalPrepass;
65
66#[derive(Component, Default, Reflect, Clone)]
68#[reflect(Component, Default, Clone)]
69pub struct MotionVectorPrepass;
70
71#[derive(Component, Default, Reflect)]
74#[reflect(Component, Default)]
75pub struct DeferredPrepass;
76
77#[derive(Component, ShaderType, Clone)]
81pub struct PreviousViewData {
82    pub view_from_world: Mat4,
83    pub clip_from_world: Mat4,
84    pub clip_from_view: Mat4,
85    pub world_from_clip: Mat4,
86    pub view_from_clip: Mat4,
87}
88
89#[derive(Resource, Default)]
90pub struct PreviousViewUniforms {
91    pub uniforms: DynamicUniformBuffer<PreviousViewData>,
92}
93
94#[derive(Component)]
95pub struct PreviousViewUniformOffset {
96    pub offset: u32,
97}
98
99#[derive(Component)]
103pub struct ViewPrepassTextures {
104    pub depth: Option<ColorAttachment>,
107    pub normal: Option<ColorAttachment>,
110    pub motion_vectors: Option<ColorAttachment>,
113    pub deferred: Option<ColorAttachment>,
116    pub deferred_lighting_pass_id: Option<ColorAttachment>,
119    pub size: Extent3d,
121}
122
123impl ViewPrepassTextures {
124    pub fn depth_view(&self) -> Option<&TextureView> {
125        self.depth.as_ref().map(|t| &t.texture.default_view)
126    }
127
128    pub fn normal_view(&self) -> Option<&TextureView> {
129        self.normal.as_ref().map(|t| &t.texture.default_view)
130    }
131
132    pub fn motion_vectors_view(&self) -> Option<&TextureView> {
133        self.motion_vectors
134            .as_ref()
135            .map(|t| &t.texture.default_view)
136    }
137
138    pub fn deferred_view(&self) -> Option<&TextureView> {
139        self.deferred.as_ref().map(|t| &t.texture.default_view)
140    }
141}
142
143pub struct Opaque3dPrepass {
149    pub batch_set_key: OpaqueNoLightmap3dBatchSetKey,
154    pub bin_key: OpaqueNoLightmap3dBinKey,
156
157    pub representative_entity: (Entity, MainEntity),
160    pub batch_range: Range<u32>,
161    pub extra_index: PhaseItemExtraIndex,
162}
163
164#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
170pub struct OpaqueNoLightmap3dBatchSetKey {
171    pub pipeline: CachedRenderPipelineId,
173
174    pub draw_function: DrawFunctionId,
176
177    pub material_bind_group_index: Option<u32>,
181
182    pub vertex_slab: SlabId,
187
188    pub index_slab: Option<SlabId>,
192}
193
194impl PhaseItemBatchSetKey for OpaqueNoLightmap3dBatchSetKey {
195    fn indexed(&self) -> bool {
196        self.index_slab.is_some()
197    }
198}
199
200#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
203pub struct OpaqueNoLightmap3dBinKey {
204    pub asset_id: UntypedAssetId,
206}
207
208impl PhaseItem for Opaque3dPrepass {
209    #[inline]
210    fn entity(&self) -> Entity {
211        self.representative_entity.0
212    }
213
214    fn main_entity(&self) -> MainEntity {
215        self.representative_entity.1
216    }
217
218    #[inline]
219    fn draw_function(&self) -> DrawFunctionId {
220        self.batch_set_key.draw_function
221    }
222
223    #[inline]
224    fn batch_range(&self) -> &Range<u32> {
225        &self.batch_range
226    }
227
228    #[inline]
229    fn batch_range_mut(&mut self) -> &mut Range<u32> {
230        &mut self.batch_range
231    }
232
233    #[inline]
234    fn extra_index(&self) -> PhaseItemExtraIndex {
235        self.extra_index.clone()
236    }
237
238    #[inline]
239    fn batch_range_and_extra_index_mut(&mut self) -> (&mut Range<u32>, &mut PhaseItemExtraIndex) {
240        (&mut self.batch_range, &mut self.extra_index)
241    }
242}
243
244impl BinnedPhaseItem for Opaque3dPrepass {
245    type BatchSetKey = OpaqueNoLightmap3dBatchSetKey;
246    type BinKey = OpaqueNoLightmap3dBinKey;
247
248    #[inline]
249    fn new(
250        batch_set_key: Self::BatchSetKey,
251        bin_key: Self::BinKey,
252        representative_entity: (Entity, MainEntity),
253        batch_range: Range<u32>,
254        extra_index: PhaseItemExtraIndex,
255    ) -> Self {
256        Opaque3dPrepass {
257            batch_set_key,
258            bin_key,
259            representative_entity,
260            batch_range,
261            extra_index,
262        }
263    }
264}
265
266impl CachedRenderPipelinePhaseItem for Opaque3dPrepass {
267    #[inline]
268    fn cached_pipeline(&self) -> CachedRenderPipelineId {
269        self.batch_set_key.pipeline
270    }
271}
272
273pub struct AlphaMask3dPrepass {
279    pub batch_set_key: OpaqueNoLightmap3dBatchSetKey,
284    pub bin_key: OpaqueNoLightmap3dBinKey,
286    pub representative_entity: (Entity, MainEntity),
287    pub batch_range: Range<u32>,
288    pub extra_index: PhaseItemExtraIndex,
289}
290
291impl PhaseItem for AlphaMask3dPrepass {
292    #[inline]
293    fn entity(&self) -> Entity {
294        self.representative_entity.0
295    }
296
297    fn main_entity(&self) -> MainEntity {
298        self.representative_entity.1
299    }
300
301    #[inline]
302    fn draw_function(&self) -> DrawFunctionId {
303        self.batch_set_key.draw_function
304    }
305
306    #[inline]
307    fn batch_range(&self) -> &Range<u32> {
308        &self.batch_range
309    }
310
311    #[inline]
312    fn batch_range_mut(&mut self) -> &mut Range<u32> {
313        &mut self.batch_range
314    }
315
316    #[inline]
317    fn extra_index(&self) -> PhaseItemExtraIndex {
318        self.extra_index.clone()
319    }
320
321    #[inline]
322    fn batch_range_and_extra_index_mut(&mut self) -> (&mut Range<u32>, &mut PhaseItemExtraIndex) {
323        (&mut self.batch_range, &mut self.extra_index)
324    }
325}
326
327impl BinnedPhaseItem for AlphaMask3dPrepass {
328    type BatchSetKey = OpaqueNoLightmap3dBatchSetKey;
329    type BinKey = OpaqueNoLightmap3dBinKey;
330
331    #[inline]
332    fn new(
333        batch_set_key: Self::BatchSetKey,
334        bin_key: Self::BinKey,
335        representative_entity: (Entity, MainEntity),
336        batch_range: Range<u32>,
337        extra_index: PhaseItemExtraIndex,
338    ) -> Self {
339        Self {
340            batch_set_key,
341            bin_key,
342            representative_entity,
343            batch_range,
344            extra_index,
345        }
346    }
347}
348
349impl CachedRenderPipelinePhaseItem for AlphaMask3dPrepass {
350    #[inline]
351    fn cached_pipeline(&self) -> CachedRenderPipelineId {
352        self.batch_set_key.pipeline
353    }
354}
355
356pub fn prepass_target_descriptors(
357    normal_prepass: bool,
358    motion_vector_prepass: bool,
359    deferred_prepass: bool,
360) -> Vec<Option<ColorTargetState>> {
361    vec![
362        normal_prepass.then_some(ColorTargetState {
363            format: NORMAL_PREPASS_FORMAT,
364            blend: None,
365            write_mask: ColorWrites::ALL,
366        }),
367        motion_vector_prepass.then_some(ColorTargetState {
368            format: MOTION_VECTOR_PREPASS_FORMAT,
369            blend: None,
370            write_mask: ColorWrites::ALL,
371        }),
372        deferred_prepass.then_some(ColorTargetState {
373            format: DEFERRED_PREPASS_FORMAT,
374            blend: None,
375            write_mask: ColorWrites::ALL,
376        }),
377        deferred_prepass.then_some(ColorTargetState {
378            format: DEFERRED_LIGHTING_PASS_ID_FORMAT,
379            blend: None,
380            write_mask: ColorWrites::ALL,
381        }),
382    ]
383}