
Currently, `check_visibility` is parameterized over a query filter that specifies the type of potentially-visible object. This has the unfortunate side effect that we need a separate system, `mark_view_visibility_as_changed_if_necessary`, to trigger view visibility change detection. That system is quite slow because it must iterate sequentially over all entities in the scene. This PR moves the query filter from `check_visibility` to a new component, `VisibilityClass`. `VisibilityClass` stores a list of type IDs, each corresponding to one of the query filters we used to use. Because `check_visibility` is no longer specialized to the query filter at the type level, Bevy now only needs to invoke it once, leading to better performance as `check_visibility` can do change detection on the fly rather than delegating it to a separate system. This commit also has ergonomic improvements, as there's no need for applications that want to add their own custom renderable components to add specializations of the `check_visibility` system to the schedule. Instead, they only need to ensure that the `ViewVisibility` component is properly kept up to date. The recommended way to do this, and the way that's demonstrated in the `custom_phase_item` and `specialized_mesh_pipeline` examples, is to make `ViewVisibility` a required component and to add the type ID to it in a component add hook. This patch does this for `Mesh3d`, `Mesh2d`, `Sprite`, `Light`, and `Node`, which means that most app code doesn't need to change at all. Note that, although this patch has a large impact on the performance of visibility determination, it doesn't actually improve the end-to-end frame time of `many_cubes`. That's because the render world was already effectively hiding the latency from `mark_view_visibility_as_changed_if_necessary`. This patch is, however, necessary for *further* improvements to `many_cubes` performance. `many_cubes` trace before:  `many_cubes` trace after:  ## Migration Guide * `check_visibility` no longer takes a `QueryFilter`, and there's no need to add it manually to your app schedule anymore for custom rendering items. Instead, entities with custom renderable components should add the appropriate type IDs to `VisibilityClass`. See `custom_phase_item` for an example.
151 lines
6.4 KiB
Rust
151 lines
6.4 KiB
Rust
use bevy_render::view::{self, Visibility};
|
||
|
||
use super::*;
|
||
|
||
/// A Directional light.
|
||
///
|
||
/// Directional lights don't exist in reality but they are a good
|
||
/// approximation for light sources VERY far away, like the sun or
|
||
/// the moon.
|
||
///
|
||
/// The light shines along the forward direction of the entity's transform. With a default transform
|
||
/// this would be along the negative-Z axis.
|
||
///
|
||
/// Valid values for `illuminance` are:
|
||
///
|
||
/// | Illuminance (lux) | Surfaces illuminated by |
|
||
/// |-------------------|------------------------------------------------|
|
||
/// | 0.0001 | Moonless, overcast night sky (starlight) |
|
||
/// | 0.002 | Moonless clear night sky with airglow |
|
||
/// | 0.05–0.3 | Full moon on a clear night |
|
||
/// | 3.4 | Dark limit of civil twilight under a clear sky |
|
||
/// | 20–50 | Public areas with dark surroundings |
|
||
/// | 50 | Family living room lights |
|
||
/// | 80 | Office building hallway/toilet lighting |
|
||
/// | 100 | Very dark overcast day |
|
||
/// | 150 | Train station platforms |
|
||
/// | 320–500 | Office lighting |
|
||
/// | 400 | Sunrise or sunset on a clear day. |
|
||
/// | 1000 | Overcast day; typical TV studio lighting |
|
||
/// | 10,000–25,000 | Full daylight (not direct sun) |
|
||
/// | 32,000–100,000 | Direct sunlight |
|
||
///
|
||
/// Source: [Wikipedia](https://en.wikipedia.org/wiki/Lux)
|
||
///
|
||
/// ## Shadows
|
||
///
|
||
/// To enable shadows, set the `shadows_enabled` property to `true`.
|
||
///
|
||
/// Shadows are produced via [cascaded shadow maps](https://developer.download.nvidia.com/SDK/10.5/opengl/src/cascaded_shadow_maps/doc/cascaded_shadow_maps.pdf).
|
||
///
|
||
/// To modify the cascade setup, such as the number of cascades or the maximum shadow distance,
|
||
/// change the [`CascadeShadowConfig`] component of the entity with the [`DirectionalLight`].
|
||
///
|
||
/// To control the resolution of the shadow maps, use the [`DirectionalLightShadowMap`] resource:
|
||
///
|
||
/// ```
|
||
/// # use bevy_app::prelude::*;
|
||
/// # use bevy_pbr::DirectionalLightShadowMap;
|
||
/// App::new()
|
||
/// .insert_resource(DirectionalLightShadowMap { size: 2048 });
|
||
/// ```
|
||
#[derive(Component, Debug, Clone, Reflect)]
|
||
#[reflect(Component, Default, Debug)]
|
||
#[require(
|
||
Cascades,
|
||
CascadesFrusta,
|
||
CascadeShadowConfig,
|
||
CascadesVisibleEntities,
|
||
Transform,
|
||
Visibility,
|
||
VisibilityClass
|
||
)]
|
||
#[component(on_add = view::add_visibility_class::<LightVisibilityClass>)]
|
||
pub struct DirectionalLight {
|
||
/// The color of the light.
|
||
///
|
||
/// By default, this is white.
|
||
pub color: Color,
|
||
|
||
/// Illuminance in lux (lumens per square meter), representing the amount of
|
||
/// light projected onto surfaces by this light source. Lux is used here
|
||
/// instead of lumens because a directional light illuminates all surfaces
|
||
/// more-or-less the same way (depending on the angle of incidence). Lumens
|
||
/// can only be specified for light sources which emit light from a specific
|
||
/// area.
|
||
pub illuminance: f32,
|
||
|
||
/// Whether this light casts shadows.
|
||
///
|
||
/// Note that shadows are rather expensive and become more so with every
|
||
/// light that casts them. In general, it's best to aggressively limit the
|
||
/// number of lights with shadows enabled to one or two at most.
|
||
pub shadows_enabled: bool,
|
||
|
||
/// Whether soft shadows are enabled, and if so, the size of the light.
|
||
///
|
||
/// Soft shadows, also known as *percentage-closer soft shadows* or PCSS,
|
||
/// cause shadows to become blurrier (i.e. their penumbra increases in
|
||
/// radius) as they extend away from objects. The blurriness of the shadow
|
||
/// depends on the size of the light; larger lights result in larger
|
||
/// penumbras and therefore blurrier shadows.
|
||
///
|
||
/// Currently, soft shadows are rather noisy if not using the temporal mode.
|
||
/// If you enable soft shadows, consider choosing
|
||
/// [`ShadowFilteringMethod::Temporal`] and enabling temporal antialiasing
|
||
/// (TAA) to smooth the noise out over time.
|
||
///
|
||
/// Note that soft shadows are significantly more expensive to render than
|
||
/// hard shadows.
|
||
#[cfg(feature = "experimental_pbr_pcss")]
|
||
pub soft_shadow_size: Option<f32>,
|
||
|
||
/// Whether this directional light contributes diffuse lighting to meshes
|
||
/// with lightmaps.
|
||
///
|
||
/// Set this to false if your lightmap baking tool bakes the direct diffuse
|
||
/// light from this directional light into the lightmaps in order to avoid
|
||
/// counting the radiance from this light twice. Note that the specular
|
||
/// portion of the light is always considered, because Bevy currently has no
|
||
/// means to bake specular light.
|
||
///
|
||
/// By default, this is set to true.
|
||
pub affects_lightmapped_mesh_diffuse: bool,
|
||
|
||
/// A value that adjusts the tradeoff between self-shadowing artifacts and
|
||
/// proximity of shadows to their casters.
|
||
///
|
||
/// This value frequently must be tuned to the specific scene; this is
|
||
/// normal and a well-known part of the shadow mapping workflow. If set too
|
||
/// low, unsightly shadow patterns appear on objects not in shadow as
|
||
/// objects incorrectly cast shadows on themselves, known as *shadow acne*.
|
||
/// If set too high, shadows detach from the objects casting them and seem
|
||
/// to "fly" off the objects, known as *Peter Panning*.
|
||
pub shadow_depth_bias: f32,
|
||
|
||
/// A bias applied along the direction of the fragment's surface normal. It
|
||
/// is scaled to the shadow map's texel size so that it is automatically
|
||
/// adjusted to the orthographic projection.
|
||
pub shadow_normal_bias: f32,
|
||
}
|
||
|
||
impl Default for DirectionalLight {
|
||
fn default() -> Self {
|
||
DirectionalLight {
|
||
color: Color::WHITE,
|
||
illuminance: light_consts::lux::AMBIENT_DAYLIGHT,
|
||
shadows_enabled: false,
|
||
shadow_depth_bias: Self::DEFAULT_SHADOW_DEPTH_BIAS,
|
||
shadow_normal_bias: Self::DEFAULT_SHADOW_NORMAL_BIAS,
|
||
affects_lightmapped_mesh_diffuse: true,
|
||
#[cfg(feature = "experimental_pbr_pcss")]
|
||
soft_shadow_size: None,
|
||
}
|
||
}
|
||
}
|
||
|
||
impl DirectionalLight {
|
||
pub const DEFAULT_SHADOW_DEPTH_BIAS: f32 = 0.02;
|
||
pub const DEFAULT_SHADOW_NORMAL_BIAS: f32 = 1.8;
|
||
}
|