bevy_core_pipeline/prepass/
mod.rs1pub mod background_motion_vectors;
29pub mod node;
30
31pub use background_motion_vectors::{
32 BackgroundMotionVectorsBindGroup, BackgroundMotionVectorsPipelineId,
33 BackgroundMotionVectorsPlugin, NoBackgroundMotionVectors,
34};
35
36use core::ops::Range;
37
38use crate::deferred::{DEFERRED_LIGHTING_PASS_ID_FORMAT, DEFERRED_PREPASS_FORMAT};
39use bevy_asset::UntypedAssetId;
40use bevy_ecs::prelude::*;
41use bevy_math::Mat4;
42use bevy_reflect::{std_traits::ReflectDefault, Reflect};
43use bevy_render::mesh::allocator::MeshSlabs;
44use bevy_render::render_phase::PhaseItemBatchSetKey;
45use bevy_render::sync_world::MainEntity;
46use bevy_render::{
47 render_phase::{
48 BinnedPhaseItem, CachedRenderPipelinePhaseItem, DrawFunctionId, PhaseItem,
49 PhaseItemExtraIndex,
50 },
51 render_resource::{
52 CachedRenderPipelineId, ColorTargetState, ColorWrites, DynamicUniformBuffer, Extent3d,
53 ShaderType, TextureFormat, TextureView,
54 },
55 texture::ColorAttachment,
56};
57
58pub const NORMAL_PREPASS_FORMAT: TextureFormat = TextureFormat::Rgb10a2Unorm;
59pub const MOTION_VECTOR_PREPASS_FORMAT: TextureFormat = TextureFormat::Rg16Float;
60
61#[derive(Component, Default, Reflect, Clone)]
63#[reflect(Component, Default, Clone)]
64pub struct DepthPrepass;
65
66#[derive(Component, Default, Reflect, Clone)]
69#[reflect(Component, Default, Clone)]
70pub struct NormalPrepass;
71
72#[derive(Component, Default, Reflect, Clone)]
77#[reflect(Component, Default, Clone)]
78pub struct MotionVectorPrepass;
79
80#[derive(Component, Default, Reflect)]
83#[reflect(Component, Default)]
84pub struct DeferredPrepass;
85
86#[derive(Component, Default, Reflect, Clone)]
88#[reflect(Component, Default, Clone)]
89#[require(DepthPrepass)]
90pub struct DepthPrepassDoubleBuffer;
91
92#[derive(Component, Default, Reflect, Clone)]
94#[reflect(Component, Default, Clone)]
95#[require(DeferredPrepass)]
96pub struct DeferredPrepassDoubleBuffer;
97
98#[derive(Component, ShaderType, Clone)]
102pub struct PreviousViewData {
103 pub view_from_world: Mat4,
104 pub clip_from_world: Mat4,
105 pub clip_from_view: Mat4,
106 pub world_from_clip: Mat4,
107 pub view_from_clip: Mat4,
108}
109
110#[derive(Resource, Default)]
111pub struct PreviousViewUniforms {
112 pub uniforms: DynamicUniformBuffer<PreviousViewData>,
113}
114
115#[derive(Component)]
116pub struct PreviousViewUniformOffset {
117 pub offset: u32,
118}
119
120#[derive(Component)]
124pub struct ViewPrepassTextures {
125 pub depth: Option<ColorAttachment>,
128 pub normal: Option<ColorAttachment>,
131 pub motion_vectors: Option<ColorAttachment>,
134 pub deferred: Option<ColorAttachment>,
137 pub deferred_lighting_pass_id: Option<ColorAttachment>,
140 pub size: Extent3d,
142}
143
144impl ViewPrepassTextures {
145 pub fn depth_view(&self) -> Option<&TextureView> {
146 self.depth.as_ref().map(|t| &t.texture.default_view)
147 }
148
149 pub fn previous_depth_view(&self) -> Option<&TextureView> {
150 self.depth
151 .as_ref()
152 .and_then(|t| t.previous_frame_texture.as_ref().map(|t| &t.default_view))
153 }
154
155 pub fn normal_view(&self) -> Option<&TextureView> {
156 self.normal.as_ref().map(|t| &t.texture.default_view)
157 }
158
159 pub fn motion_vectors_view(&self) -> Option<&TextureView> {
160 self.motion_vectors
161 .as_ref()
162 .map(|t| &t.texture.default_view)
163 }
164
165 pub fn deferred_view(&self) -> Option<&TextureView> {
166 self.deferred.as_ref().map(|t| &t.texture.default_view)
167 }
168
169 pub fn previous_deferred_view(&self) -> Option<&TextureView> {
170 self.deferred
171 .as_ref()
172 .and_then(|t| t.previous_frame_texture.as_ref().map(|t| &t.default_view))
173 }
174}
175
176pub struct Opaque3dPrepass {
182 pub batch_set_key: OpaqueNoLightmap3dBatchSetKey,
187 pub bin_key: OpaqueNoLightmap3dBinKey,
189
190 pub representative_entity: (Entity, MainEntity),
193 pub batch_range: Range<u32>,
194 pub extra_index: PhaseItemExtraIndex,
195}
196
197#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
203pub struct OpaqueNoLightmap3dBatchSetKey {
204 pub pipeline: CachedRenderPipelineId,
206
207 pub draw_function: DrawFunctionId,
209
210 pub material_bind_group_index: Option<u32>,
214
215 pub slabs: MeshSlabs,
222}
223
224impl PhaseItemBatchSetKey for OpaqueNoLightmap3dBatchSetKey {
225 fn indexed(&self) -> bool {
226 self.slabs.index_slab_id.is_some()
227 }
228}
229
230#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
233pub struct OpaqueNoLightmap3dBinKey {
234 pub asset_id: UntypedAssetId,
236}
237
238impl PhaseItem for Opaque3dPrepass {
239 #[inline]
240 fn entity(&self) -> Entity {
241 self.representative_entity.0
242 }
243
244 fn main_entity(&self) -> MainEntity {
245 self.representative_entity.1
246 }
247
248 #[inline]
249 fn draw_function(&self) -> DrawFunctionId {
250 self.batch_set_key.draw_function
251 }
252
253 #[inline]
254 fn batch_range(&self) -> &Range<u32> {
255 &self.batch_range
256 }
257
258 #[inline]
259 fn batch_range_mut(&mut self) -> &mut Range<u32> {
260 &mut self.batch_range
261 }
262
263 #[inline]
264 fn extra_index(&self) -> PhaseItemExtraIndex {
265 self.extra_index.clone()
266 }
267
268 #[inline]
269 fn batch_range_and_extra_index_mut(&mut self) -> (&mut Range<u32>, &mut PhaseItemExtraIndex) {
270 (&mut self.batch_range, &mut self.extra_index)
271 }
272}
273
274impl BinnedPhaseItem for Opaque3dPrepass {
275 type BatchSetKey = OpaqueNoLightmap3dBatchSetKey;
276 type BinKey = OpaqueNoLightmap3dBinKey;
277
278 #[inline]
279 fn new(
280 batch_set_key: Self::BatchSetKey,
281 bin_key: Self::BinKey,
282 representative_entity: (Entity, MainEntity),
283 batch_range: Range<u32>,
284 extra_index: PhaseItemExtraIndex,
285 ) -> Self {
286 Opaque3dPrepass {
287 batch_set_key,
288 bin_key,
289 representative_entity,
290 batch_range,
291 extra_index,
292 }
293 }
294}
295
296impl CachedRenderPipelinePhaseItem for Opaque3dPrepass {
297 #[inline]
298 fn cached_pipeline(&self) -> CachedRenderPipelineId {
299 self.batch_set_key.pipeline
300 }
301}
302
303pub struct AlphaMask3dPrepass {
309 pub batch_set_key: OpaqueNoLightmap3dBatchSetKey,
314 pub bin_key: OpaqueNoLightmap3dBinKey,
316 pub representative_entity: (Entity, MainEntity),
317 pub batch_range: Range<u32>,
318 pub extra_index: PhaseItemExtraIndex,
319}
320
321impl PhaseItem for AlphaMask3dPrepass {
322 #[inline]
323 fn entity(&self) -> Entity {
324 self.representative_entity.0
325 }
326
327 fn main_entity(&self) -> MainEntity {
328 self.representative_entity.1
329 }
330
331 #[inline]
332 fn draw_function(&self) -> DrawFunctionId {
333 self.batch_set_key.draw_function
334 }
335
336 #[inline]
337 fn batch_range(&self) -> &Range<u32> {
338 &self.batch_range
339 }
340
341 #[inline]
342 fn batch_range_mut(&mut self) -> &mut Range<u32> {
343 &mut self.batch_range
344 }
345
346 #[inline]
347 fn extra_index(&self) -> PhaseItemExtraIndex {
348 self.extra_index.clone()
349 }
350
351 #[inline]
352 fn batch_range_and_extra_index_mut(&mut self) -> (&mut Range<u32>, &mut PhaseItemExtraIndex) {
353 (&mut self.batch_range, &mut self.extra_index)
354 }
355}
356
357impl BinnedPhaseItem for AlphaMask3dPrepass {
358 type BatchSetKey = OpaqueNoLightmap3dBatchSetKey;
359 type BinKey = OpaqueNoLightmap3dBinKey;
360
361 #[inline]
362 fn new(
363 batch_set_key: Self::BatchSetKey,
364 bin_key: Self::BinKey,
365 representative_entity: (Entity, MainEntity),
366 batch_range: Range<u32>,
367 extra_index: PhaseItemExtraIndex,
368 ) -> Self {
369 Self {
370 batch_set_key,
371 bin_key,
372 representative_entity,
373 batch_range,
374 extra_index,
375 }
376 }
377}
378
379impl CachedRenderPipelinePhaseItem for AlphaMask3dPrepass {
380 #[inline]
381 fn cached_pipeline(&self) -> CachedRenderPipelineId {
382 self.batch_set_key.pipeline
383 }
384}
385
386pub fn prepass_target_descriptors(
387 normal_prepass: bool,
388 motion_vector_prepass: bool,
389 deferred_prepass: bool,
390) -> Vec<Option<ColorTargetState>> {
391 vec![
392 normal_prepass.then_some(ColorTargetState {
393 format: NORMAL_PREPASS_FORMAT,
394 blend: None,
395 write_mask: ColorWrites::ALL,
396 }),
397 motion_vector_prepass.then_some(ColorTargetState {
398 format: MOTION_VECTOR_PREPASS_FORMAT,
399 blend: None,
400 write_mask: ColorWrites::ALL,
401 }),
402 deferred_prepass.then_some(ColorTargetState {
403 format: DEFERRED_PREPASS_FORMAT,
404 blend: None,
405 write_mask: ColorWrites::ALL,
406 }),
407 deferred_prepass.then_some(ColorTargetState {
408 format: DEFERRED_LIGHTING_PASS_ID_FORMAT,
409 blend: None,
410 write_mask: ColorWrites::ALL,
411 }),
412 ]
413}