Path: blob/main/crates/bevy_pbr/src/transmission/phase.rs
9434 views
use core::ops::Range;12use bevy_camera::{Camera, Camera3d};3use bevy_ecs::{4entity::Entity,5query::With,6system::{Local, Query, ResMut},7};8use bevy_material::{descriptor::CachedRenderPipelineId, labels::DrawFunctionId};9use bevy_math::FloatOrd;10use bevy_platform::collections::HashSet;11use bevy_render::{12render_phase::{13CachedRenderPipelinePhaseItem, PhaseItem, PhaseItemExtraIndex, SortedPhaseItem,14ViewSortedRenderPhases,15},16sync_world::MainEntity,17view::RetainedViewEntity,18Extract,19};2021pub struct Transmissive3d {22pub distance: f32,23pub pipeline: CachedRenderPipelineId,24pub entity: (Entity, MainEntity),25pub draw_function: DrawFunctionId,26pub batch_range: Range<u32>,27pub extra_index: PhaseItemExtraIndex,28/// Whether the mesh in question is indexed (uses an index buffer in29/// addition to its vertex buffer).30pub indexed: bool,31}3233impl PhaseItem for Transmissive3d {34/// For now, automatic batching is disabled for transmissive items because their rendering is35/// split into multiple steps depending on [`crate::ScreenSpaceTransmission::steps`],36/// which the batching system doesn't currently know about.37///38/// Having batching enabled would cause the same item to be drawn multiple times across different39/// steps, whenever the batching range crossed a step boundary.40///41/// Eventually, we could add support for this by having the batching system break up the batch ranges42/// using the same logic as the transmissive pass, but for now it's simpler to just disable batching.43const AUTOMATIC_BATCHING: bool = false;4445#[inline]46fn entity(&self) -> Entity {47self.entity.048}4950#[inline]51fn main_entity(&self) -> MainEntity {52self.entity.153}5455#[inline]56fn draw_function(&self) -> DrawFunctionId {57self.draw_function58}5960#[inline]61fn batch_range(&self) -> &Range<u32> {62&self.batch_range63}6465#[inline]66fn batch_range_mut(&mut self) -> &mut Range<u32> {67&mut self.batch_range68}6970#[inline]71fn extra_index(&self) -> PhaseItemExtraIndex {72self.extra_index.clone()73}7475#[inline]76fn batch_range_and_extra_index_mut(&mut self) -> (&mut Range<u32>, &mut PhaseItemExtraIndex) {77(&mut self.batch_range, &mut self.extra_index)78}79}8081impl SortedPhaseItem for Transmissive3d {82// NOTE: Values increase towards the camera. Back-to-front ordering for transmissive means we need an ascending sort.83type SortKey = FloatOrd;8485#[inline]86fn sort_key(&self) -> Self::SortKey {87FloatOrd(self.distance)88}8990#[inline]91fn sort(items: &mut [Self]) {92radsort::sort_by_key(items, |item| item.distance);93}9495#[inline]96fn indexed(&self) -> bool {97self.indexed98}99}100101impl CachedRenderPipelinePhaseItem for Transmissive3d {102#[inline]103fn cached_pipeline(&self) -> CachedRenderPipelineId {104self.pipeline105}106}107108pub fn extract_transmissive_camera_phases(109mut transmissive_3d_phases: ResMut<ViewSortedRenderPhases<Transmissive3d>>,110cameras: Extract<Query<(Entity, &Camera), With<Camera3d>>>,111mut live_entities: Local<HashSet<RetainedViewEntity>>,112) {113live_entities.clear();114115for (main_entity, camera) in &cameras {116if !camera.is_active {117continue;118}119120// This is the main camera, so use the first subview index (0).121let retained_view_entity = RetainedViewEntity::new(main_entity.into(), None, 0);122123transmissive_3d_phases.insert_or_clear(retained_view_entity);124live_entities.insert(retained_view_entity);125}126127transmissive_3d_phases.retain(|view_entity, _| live_entities.contains(view_entity));128}129130131