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)]
71#[reflect(Component, Default, Clone)]
72pub struct MotionVectorPrepass;
73
74#[derive(Component, Default, Reflect)]
77#[reflect(Component, Default)]
78pub struct DeferredPrepass;
79
80#[derive(Component, Default, Reflect, Clone)]
82#[reflect(Component, Default, Clone)]
83#[require(DepthPrepass)]
84pub struct DepthPrepassDoubleBuffer;
85
86#[derive(Component, Default, Reflect, Clone)]
88#[reflect(Component, Default, Clone)]
89#[require(DeferredPrepass)]
90pub struct DeferredPrepassDoubleBuffer;
91
92#[derive(Component, ShaderType, Clone)]
96pub struct PreviousViewData {
97 pub view_from_world: Mat4,
98 pub clip_from_world: Mat4,
99 pub clip_from_view: Mat4,
100 pub world_from_clip: Mat4,
101 pub view_from_clip: Mat4,
102}
103
104#[derive(Resource, Default)]
105pub struct PreviousViewUniforms {
106 pub uniforms: DynamicUniformBuffer<PreviousViewData>,
107}
108
109#[derive(Component)]
110pub struct PreviousViewUniformOffset {
111 pub offset: u32,
112}
113
114#[derive(Component)]
118pub struct ViewPrepassTextures {
119 pub depth: Option<ColorAttachment>,
122 pub normal: Option<ColorAttachment>,
125 pub motion_vectors: Option<ColorAttachment>,
128 pub deferred: Option<ColorAttachment>,
131 pub deferred_lighting_pass_id: Option<ColorAttachment>,
134 pub size: Extent3d,
136}
137
138impl ViewPrepassTextures {
139 pub fn depth_view(&self) -> Option<&TextureView> {
140 self.depth.as_ref().map(|t| &t.texture.default_view)
141 }
142
143 pub fn previous_depth_view(&self) -> Option<&TextureView> {
144 self.depth
145 .as_ref()
146 .and_then(|t| t.previous_frame_texture.as_ref().map(|t| &t.default_view))
147 }
148
149 pub fn normal_view(&self) -> Option<&TextureView> {
150 self.normal.as_ref().map(|t| &t.texture.default_view)
151 }
152
153 pub fn motion_vectors_view(&self) -> Option<&TextureView> {
154 self.motion_vectors
155 .as_ref()
156 .map(|t| &t.texture.default_view)
157 }
158
159 pub fn deferred_view(&self) -> Option<&TextureView> {
160 self.deferred.as_ref().map(|t| &t.texture.default_view)
161 }
162
163 pub fn previous_deferred_view(&self) -> Option<&TextureView> {
164 self.deferred
165 .as_ref()
166 .and_then(|t| t.previous_frame_texture.as_ref().map(|t| &t.default_view))
167 }
168}
169
170pub struct Opaque3dPrepass {
176 pub batch_set_key: OpaqueNoLightmap3dBatchSetKey,
181 pub bin_key: OpaqueNoLightmap3dBinKey,
183
184 pub representative_entity: (Entity, MainEntity),
187 pub batch_range: Range<u32>,
188 pub extra_index: PhaseItemExtraIndex,
189}
190
191#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
197pub struct OpaqueNoLightmap3dBatchSetKey {
198 pub pipeline: CachedRenderPipelineId,
200
201 pub draw_function: DrawFunctionId,
203
204 pub material_bind_group_index: Option<u32>,
208
209 pub vertex_slab: SlabId,
214
215 pub index_slab: Option<SlabId>,
219}
220
221impl PhaseItemBatchSetKey for OpaqueNoLightmap3dBatchSetKey {
222 fn indexed(&self) -> bool {
223 self.index_slab.is_some()
224 }
225}
226
227#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
230pub struct OpaqueNoLightmap3dBinKey {
231 pub asset_id: UntypedAssetId,
233}
234
235impl PhaseItem for Opaque3dPrepass {
236 #[inline]
237 fn entity(&self) -> Entity {
238 self.representative_entity.0
239 }
240
241 fn main_entity(&self) -> MainEntity {
242 self.representative_entity.1
243 }
244
245 #[inline]
246 fn draw_function(&self) -> DrawFunctionId {
247 self.batch_set_key.draw_function
248 }
249
250 #[inline]
251 fn batch_range(&self) -> &Range<u32> {
252 &self.batch_range
253 }
254
255 #[inline]
256 fn batch_range_mut(&mut self) -> &mut Range<u32> {
257 &mut self.batch_range
258 }
259
260 #[inline]
261 fn extra_index(&self) -> PhaseItemExtraIndex {
262 self.extra_index.clone()
263 }
264
265 #[inline]
266 fn batch_range_and_extra_index_mut(&mut self) -> (&mut Range<u32>, &mut PhaseItemExtraIndex) {
267 (&mut self.batch_range, &mut self.extra_index)
268 }
269}
270
271impl BinnedPhaseItem for Opaque3dPrepass {
272 type BatchSetKey = OpaqueNoLightmap3dBatchSetKey;
273 type BinKey = OpaqueNoLightmap3dBinKey;
274
275 #[inline]
276 fn new(
277 batch_set_key: Self::BatchSetKey,
278 bin_key: Self::BinKey,
279 representative_entity: (Entity, MainEntity),
280 batch_range: Range<u32>,
281 extra_index: PhaseItemExtraIndex,
282 ) -> Self {
283 Opaque3dPrepass {
284 batch_set_key,
285 bin_key,
286 representative_entity,
287 batch_range,
288 extra_index,
289 }
290 }
291}
292
293impl CachedRenderPipelinePhaseItem for Opaque3dPrepass {
294 #[inline]
295 fn cached_pipeline(&self) -> CachedRenderPipelineId {
296 self.batch_set_key.pipeline
297 }
298}
299
300pub struct AlphaMask3dPrepass {
306 pub batch_set_key: OpaqueNoLightmap3dBatchSetKey,
311 pub bin_key: OpaqueNoLightmap3dBinKey,
313 pub representative_entity: (Entity, MainEntity),
314 pub batch_range: Range<u32>,
315 pub extra_index: PhaseItemExtraIndex,
316}
317
318impl PhaseItem for AlphaMask3dPrepass {
319 #[inline]
320 fn entity(&self) -> Entity {
321 self.representative_entity.0
322 }
323
324 fn main_entity(&self) -> MainEntity {
325 self.representative_entity.1
326 }
327
328 #[inline]
329 fn draw_function(&self) -> DrawFunctionId {
330 self.batch_set_key.draw_function
331 }
332
333 #[inline]
334 fn batch_range(&self) -> &Range<u32> {
335 &self.batch_range
336 }
337
338 #[inline]
339 fn batch_range_mut(&mut self) -> &mut Range<u32> {
340 &mut self.batch_range
341 }
342
343 #[inline]
344 fn extra_index(&self) -> PhaseItemExtraIndex {
345 self.extra_index.clone()
346 }
347
348 #[inline]
349 fn batch_range_and_extra_index_mut(&mut self) -> (&mut Range<u32>, &mut PhaseItemExtraIndex) {
350 (&mut self.batch_range, &mut self.extra_index)
351 }
352}
353
354impl BinnedPhaseItem for AlphaMask3dPrepass {
355 type BatchSetKey = OpaqueNoLightmap3dBatchSetKey;
356 type BinKey = OpaqueNoLightmap3dBinKey;
357
358 #[inline]
359 fn new(
360 batch_set_key: Self::BatchSetKey,
361 bin_key: Self::BinKey,
362 representative_entity: (Entity, MainEntity),
363 batch_range: Range<u32>,
364 extra_index: PhaseItemExtraIndex,
365 ) -> Self {
366 Self {
367 batch_set_key,
368 bin_key,
369 representative_entity,
370 batch_range,
371 extra_index,
372 }
373 }
374}
375
376impl CachedRenderPipelinePhaseItem for AlphaMask3dPrepass {
377 #[inline]
378 fn cached_pipeline(&self) -> CachedRenderPipelineId {
379 self.batch_set_key.pipeline
380 }
381}
382
383pub fn prepass_target_descriptors(
384 normal_prepass: bool,
385 motion_vector_prepass: bool,
386 deferred_prepass: bool,
387) -> Vec<Option<ColorTargetState>> {
388 vec![
389 normal_prepass.then_some(ColorTargetState {
390 format: NORMAL_PREPASS_FORMAT,
391 blend: None,
392 write_mask: ColorWrites::ALL,
393 }),
394 motion_vector_prepass.then_some(ColorTargetState {
395 format: MOTION_VECTOR_PREPASS_FORMAT,
396 blend: None,
397 write_mask: ColorWrites::ALL,
398 }),
399 deferred_prepass.then_some(ColorTargetState {
400 format: DEFERRED_PREPASS_FORMAT,
401 blend: None,
402 write_mask: ColorWrites::ALL,
403 }),
404 deferred_prepass.then_some(ColorTargetState {
405 format: DEFERRED_LIGHTING_PASS_ID_FORMAT,
406 blend: None,
407 write_mask: ColorWrites::ALL,
408 }),
409 ]
410}