Skip to main content

bevy_pbr/transmission/
mod.rs

1mod node;
2mod phase;
3mod texture;
4
5use bevy_app::{App, Plugin};
6use bevy_core_pipeline::{
7    core_3d::{main_opaque_pass_3d, main_transparent_pass_3d},
8    schedule::{Core3d, Core3dSystems},
9};
10use bevy_ecs::{prelude::*, schedule::IntoScheduleConfigs};
11use bevy_reflect::prelude::*;
12use bevy_render::{
13    extract_component::{ExtractComponent, ExtractComponentPlugin},
14    render_phase::{sort_phase_system, AddRenderCommand, DrawFunctions, ViewSortedRenderPhases},
15    ExtractSchedule, Render, RenderApp, RenderSystems,
16};
17pub use node::main_transmissive_pass_3d;
18pub use phase::Transmissive3d;
19pub use texture::ViewTransmissionTexture;
20
21use texture::prepare_core_3d_transmission_textures;
22
23use crate::{DrawMaterial, MeshPipelineKey};
24
25/// Enables screen-space transmission for cameras.
26pub struct ScreenSpaceTransmissionPlugin;
27
28impl Plugin for ScreenSpaceTransmissionPlugin {
29    fn build(&self, app: &mut App) {
30        app.add_plugins(ExtractComponentPlugin::<ScreenSpaceTransmission>::default());
31
32        let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
33            return;
34        };
35
36        render_app
37            .init_resource::<DrawFunctions<Transmissive3d>>()
38            .init_resource::<ViewSortedRenderPhases<Transmissive3d>>()
39            .add_render_command::<Transmissive3d, DrawMaterial>()
40            .add_systems(
41                Render,
42                sort_phase_system::<Transmissive3d>.in_set(RenderSystems::PhaseSort),
43            )
44            .add_systems(ExtractSchedule, phase::extract_transmissive_camera_phases)
45            .add_systems(
46                Render,
47                prepare_core_3d_transmission_textures.in_set(RenderSystems::PrepareResources),
48            )
49            .add_systems(
50                Core3d,
51                main_transmissive_pass_3d
52                    .after(main_opaque_pass_3d)
53                    .before(main_transparent_pass_3d)
54                    .in_set(Core3dSystems::MainPass),
55            );
56    }
57}
58
59/// Configures transmission behavior, offering a trade-off between performance and visual fidelity.
60#[derive(Component, Reflect, Clone, ExtractComponent)]
61#[reflect(Component, Default, Clone)]
62#[extract_app(RenderApp)]
63pub struct ScreenSpaceTransmission {
64    /// How many individual steps should be performed in the `Transmissive3d` pass.
65    ///
66    /// Roughly corresponds to how many layers of transparency are rendered for screen space
67    /// specular transmissive objects. Each step requires making one additional
68    /// texture copy, so it's recommended to keep this number to a reasonably low value. Defaults to `1`.
69    ///
70    /// ### Notes
71    ///
72    /// - No copies will be performed if there are no transmissive materials currently being rendered,
73    ///   regardless of this setting.
74    /// - Setting this to `0` disables the screen-space refraction effect entirely, and falls
75    ///   back to refracting only the environment map light's texture.
76    /// - If set to more than `0`, any opaque [`clear_color`](bevy_camera::Camera::clear_color) will obscure the environment
77    ///   map light's texture, preventing it from being visible through transmissive materials. If you'd like
78    ///   to still have the environment map show up in your refractions, you can set the clear color's alpha to `0.0`.
79    ///   Keep in mind that depending on the platform and your window settings, this may cause the window to become
80    ///   transparent.
81    pub steps: usize,
82    /// The quality of the screen space specular transmission blur effect, applied to whatever's behind transmissive
83    /// objects when their `roughness` is greater than `0.0`.
84    ///
85    /// Higher qualities are more GPU-intensive.
86    ///
87    /// **Note:** You can get better-looking results at any quality level by enabling TAA. See: `TemporalAntiAliasPlugin`
88    pub quality: ScreenSpaceTransmissionQuality,
89}
90
91impl Default for ScreenSpaceTransmission {
92    fn default() -> Self {
93        Self {
94            steps: 1,
95            quality: Default::default(),
96        }
97    }
98}
99
100/// The quality of the screen space transmission blur effect, applied to whatever's behind transmissive
101/// objects when their `roughness` is greater than `0.0`.
102///
103/// Higher qualities are more GPU-intensive.
104///
105/// **Note:** You can get better-looking results at any quality level by enabling TAA. See: `TemporalAntiAliasPlugin`
106#[derive(Default, Clone, Copy, Reflect, PartialEq, PartialOrd, Debug)]
107#[reflect(Default, Clone, Debug, PartialEq)]
108pub enum ScreenSpaceTransmissionQuality {
109    /// Best performance at the cost of quality. Suitable for lower end GPUs. (e.g. Mobile)
110    ///
111    /// `num_taps` = 4
112    Low,
113
114    /// A balanced option between quality and performance.
115    ///
116    /// `num_taps` = 8
117    #[default]
118    Medium,
119
120    /// Better quality. Suitable for high end GPUs. (e.g. Desktop)
121    ///
122    /// `num_taps` = 16
123    High,
124
125    /// The highest quality, suitable for non-realtime rendering. (e.g. Pre-rendered cinematics and photo mode)
126    ///
127    /// `num_taps` = 32
128    Ultra,
129}
130
131impl ScreenSpaceTransmissionQuality {
132    pub const fn pipeline_key(self) -> MeshPipelineKey {
133        match self {
134            ScreenSpaceTransmissionQuality::Low => {
135                MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_LOW
136            }
137            ScreenSpaceTransmissionQuality::Medium => {
138                MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_MEDIUM
139            }
140            ScreenSpaceTransmissionQuality::High => {
141                MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_HIGH
142            }
143            ScreenSpaceTransmissionQuality::Ultra => {
144                MeshPipelineKey::SCREEN_SPACE_SPECULAR_TRANSMISSION_ULTRA
145            }
146        }
147    }
148}