Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_pbr/src/transmission/phase.rs
9434 views
1
use core::ops::Range;
2
3
use bevy_camera::{Camera, Camera3d};
4
use bevy_ecs::{
5
entity::Entity,
6
query::With,
7
system::{Local, Query, ResMut},
8
};
9
use bevy_material::{descriptor::CachedRenderPipelineId, labels::DrawFunctionId};
10
use bevy_math::FloatOrd;
11
use bevy_platform::collections::HashSet;
12
use bevy_render::{
13
render_phase::{
14
CachedRenderPipelinePhaseItem, PhaseItem, PhaseItemExtraIndex, SortedPhaseItem,
15
ViewSortedRenderPhases,
16
},
17
sync_world::MainEntity,
18
view::RetainedViewEntity,
19
Extract,
20
};
21
22
pub struct Transmissive3d {
23
pub distance: f32,
24
pub pipeline: CachedRenderPipelineId,
25
pub entity: (Entity, MainEntity),
26
pub draw_function: DrawFunctionId,
27
pub batch_range: Range<u32>,
28
pub extra_index: PhaseItemExtraIndex,
29
/// Whether the mesh in question is indexed (uses an index buffer in
30
/// addition to its vertex buffer).
31
pub indexed: bool,
32
}
33
34
impl PhaseItem for Transmissive3d {
35
/// For now, automatic batching is disabled for transmissive items because their rendering is
36
/// split into multiple steps depending on [`crate::ScreenSpaceTransmission::steps`],
37
/// which the batching system doesn't currently know about.
38
///
39
/// Having batching enabled would cause the same item to be drawn multiple times across different
40
/// steps, whenever the batching range crossed a step boundary.
41
///
42
/// Eventually, we could add support for this by having the batching system break up the batch ranges
43
/// using the same logic as the transmissive pass, but for now it's simpler to just disable batching.
44
const AUTOMATIC_BATCHING: bool = false;
45
46
#[inline]
47
fn entity(&self) -> Entity {
48
self.entity.0
49
}
50
51
#[inline]
52
fn main_entity(&self) -> MainEntity {
53
self.entity.1
54
}
55
56
#[inline]
57
fn draw_function(&self) -> DrawFunctionId {
58
self.draw_function
59
}
60
61
#[inline]
62
fn batch_range(&self) -> &Range<u32> {
63
&self.batch_range
64
}
65
66
#[inline]
67
fn batch_range_mut(&mut self) -> &mut Range<u32> {
68
&mut self.batch_range
69
}
70
71
#[inline]
72
fn extra_index(&self) -> PhaseItemExtraIndex {
73
self.extra_index.clone()
74
}
75
76
#[inline]
77
fn batch_range_and_extra_index_mut(&mut self) -> (&mut Range<u32>, &mut PhaseItemExtraIndex) {
78
(&mut self.batch_range, &mut self.extra_index)
79
}
80
}
81
82
impl SortedPhaseItem for Transmissive3d {
83
// NOTE: Values increase towards the camera. Back-to-front ordering for transmissive means we need an ascending sort.
84
type SortKey = FloatOrd;
85
86
#[inline]
87
fn sort_key(&self) -> Self::SortKey {
88
FloatOrd(self.distance)
89
}
90
91
#[inline]
92
fn sort(items: &mut [Self]) {
93
radsort::sort_by_key(items, |item| item.distance);
94
}
95
96
#[inline]
97
fn indexed(&self) -> bool {
98
self.indexed
99
}
100
}
101
102
impl CachedRenderPipelinePhaseItem for Transmissive3d {
103
#[inline]
104
fn cached_pipeline(&self) -> CachedRenderPipelineId {
105
self.pipeline
106
}
107
}
108
109
pub fn extract_transmissive_camera_phases(
110
mut transmissive_3d_phases: ResMut<ViewSortedRenderPhases<Transmissive3d>>,
111
cameras: Extract<Query<(Entity, &Camera), With<Camera3d>>>,
112
mut live_entities: Local<HashSet<RetainedViewEntity>>,
113
) {
114
live_entities.clear();
115
116
for (main_entity, camera) in &cameras {
117
if !camera.is_active {
118
continue;
119
}
120
121
// This is the main camera, so use the first subview index (0).
122
let retained_view_entity = RetainedViewEntity::new(main_entity.into(), None, 0);
123
124
transmissive_3d_phases.insert_or_clear(retained_view_entity);
125
live_entities.insert(retained_view_entity);
126
}
127
128
transmissive_3d_phases.retain(|view_entity, _| live_entities.contains(view_entity));
129
}
130
131