bevy_light (#19991)
# Objective - make lights usable without bevy_render ## Solution - make a new crate for lights to live in ## Testing - 3d_scene, lighting, volumetric_fog, ssr, transmission, pcss, light_textures Note: no breaking changes because of re-exports, except for light textures, which were introduced this cycle so it doesn't matter anyways
This commit is contained in:
parent
a1139c23c6
commit
537adcc3f7
44
crates/bevy_light/Cargo.toml
Normal file
44
crates/bevy_light/Cargo.toml
Normal file
@ -0,0 +1,44 @@
|
||||
[package]
|
||||
name = "bevy_light"
|
||||
version = "0.17.0-dev"
|
||||
edition = "2024"
|
||||
description = "Keeps the lights on at Bevy Engine"
|
||||
homepage = "https://bevy.org"
|
||||
repository = "https://github.com/bevyengine/bevy"
|
||||
license = "MIT OR Apache-2.0"
|
||||
keywords = ["bevy"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.17.0-dev" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.17.0-dev" }
|
||||
bevy_image = { path = "../bevy_image", version = "0.17.0-dev" }
|
||||
bevy_mesh = { path = "../bevy_mesh", version = "0.17.0-dev" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.17.0-dev" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.17.0-dev" }
|
||||
bevy_camera = { path = "../bevy_camera", version = "0.17.0-dev" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.17.0-dev" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.17.0-dev" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.17.0-dev" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.17.0-dev" }
|
||||
bevy_platform = { path = "../bevy_platform", version = "0.17.0-dev" }
|
||||
bevy_color = { path = "../bevy_color", version = "0.17.0-dev", features = [
|
||||
"serialize",
|
||||
] }
|
||||
|
||||
# other
|
||||
serde = { version = "1", default-features = false, features = ["derive"] }
|
||||
tracing = { version = "0.1", default-features = false }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
experimental_pbr_pcss = []
|
||||
webgl = []
|
||||
webgpu = []
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["-Zunstable-options", "--generate-link-to-definition"]
|
||||
all-features = true
|
176
crates/bevy_light/LICENSE-APACHE
Normal file
176
crates/bevy_light/LICENSE-APACHE
Normal file
@ -0,0 +1,176 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
19
crates/bevy_light/LICENSE-MIT
Normal file
19
crates/bevy_light/LICENSE-MIT
Normal file
@ -0,0 +1,19 @@
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -2,7 +2,6 @@ use bevy_camera::Camera;
|
||||
use bevy_color::Color;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_render::{extract_component::ExtractComponent, extract_resource::ExtractResource};
|
||||
|
||||
/// An ambient light, which lights the entire scene equally.
|
||||
///
|
||||
@ -16,14 +15,14 @@ use bevy_render::{extract_component::ExtractComponent, extract_resource::Extract
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::system::ResMut;
|
||||
/// # use bevy_pbr::AmbientLight;
|
||||
/// # use bevy_light::AmbientLight;
|
||||
/// fn setup_ambient_light(mut ambient_light: ResMut<AmbientLight>) {
|
||||
/// ambient_light.brightness = 100.0;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`LightPlugin`]: crate::LightPlugin
|
||||
#[derive(Resource, Component, Clone, Debug, ExtractResource, ExtractComponent, Reflect)]
|
||||
#[derive(Resource, Component, Clone, Debug, Reflect)]
|
||||
#[reflect(Resource, Component, Debug, Default, Clone)]
|
||||
#[require(Camera)]
|
||||
pub struct AmbientLight {
|
@ -11,8 +11,8 @@ use crate::{DirectionalLight, DirectionalLightShadowMap};
|
||||
/// Prefer using [`CascadeShadowConfigBuilder`] to construct an instance.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_pbr::CascadeShadowConfig;
|
||||
/// # use bevy_pbr::CascadeShadowConfigBuilder;
|
||||
/// # use bevy_light::CascadeShadowConfig;
|
||||
/// # use bevy_light::CascadeShadowConfigBuilder;
|
||||
/// # use bevy_utils::default;
|
||||
/// #
|
||||
/// let config: CascadeShadowConfig = CascadeShadowConfigBuilder {
|
@ -22,10 +22,7 @@ use super::{
|
||||
ClusterConfig, ClusterFarZMode, ClusteredDecal, Clusters, GlobalClusterSettings,
|
||||
GlobalVisibleClusterableObjects, VisibleClusterableObjects,
|
||||
};
|
||||
use crate::{
|
||||
prelude::EnvironmentMapLight, ExtractedPointLight, LightProbe, PointLight, SpotLight,
|
||||
VolumetricLight,
|
||||
};
|
||||
use crate::{EnvironmentMapLight, LightProbe, PointLight, SpotLight, VolumetricLight};
|
||||
|
||||
const NDC_MIN: Vec2 = Vec2::NEG_ONE;
|
||||
const NDC_MAX: Vec2 = Vec2::ONE;
|
||||
@ -57,7 +54,7 @@ impl ClusterableObjectAssignmentData {
|
||||
/// Data needed to assign objects to clusters that's specific to the type of
|
||||
/// clusterable object.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub(crate) enum ClusterableObjectType {
|
||||
pub enum ClusterableObjectType {
|
||||
/// Data needed to assign point lights to clusters.
|
||||
PointLight {
|
||||
/// Whether shadows are enabled for this point light.
|
||||
@ -105,7 +102,7 @@ impl ClusterableObjectType {
|
||||
/// Generally, we sort first by type, then, for lights, by whether shadows
|
||||
/// are enabled (enabled before disabled), and then whether volumetrics are
|
||||
/// enabled (enabled before disabled).
|
||||
pub(crate) fn ordering(&self) -> (u8, bool, bool) {
|
||||
pub fn ordering(&self) -> (u8, bool, bool) {
|
||||
match *self {
|
||||
ClusterableObjectType::PointLight {
|
||||
shadows_enabled,
|
||||
@ -121,23 +118,6 @@ impl ClusterableObjectType {
|
||||
ClusterableObjectType::Decal => (4, false, false),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates the [`ClusterableObjectType`] data for a point or spot light.
|
||||
pub(crate) fn from_point_or_spot_light(
|
||||
point_light: &ExtractedPointLight,
|
||||
) -> ClusterableObjectType {
|
||||
match point_light.spot_light_angles {
|
||||
Some((_, outer_angle)) => ClusterableObjectType::SpotLight {
|
||||
outer_angle,
|
||||
shadows_enabled: point_light.shadows_enabled,
|
||||
volumetric: point_light.volumetric,
|
||||
},
|
||||
None => ClusterableObjectType::PointLight {
|
||||
shadows_enabled: point_light.shadows_enabled,
|
||||
volumetric: point_light.volumetric,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Run this before update_point_light_frusta!
|
@ -17,15 +17,10 @@ use bevy_image::Image;
|
||||
use bevy_math::{AspectRatio, UVec2, UVec3, Vec3Swizzles as _};
|
||||
use bevy_platform::collections::HashSet;
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||
use bevy_render::extract_component::ExtractComponent;
|
||||
use bevy_transform::components::Transform;
|
||||
use tracing::warn;
|
||||
|
||||
pub(crate) use crate::cluster::assign::assign_objects_to_clusters;
|
||||
|
||||
pub(crate) mod assign;
|
||||
mod extract_and_prepare;
|
||||
pub use extract_and_prepare::*;
|
||||
pub mod assign;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
@ -106,14 +101,14 @@ pub enum ClusterConfig {
|
||||
#[derive(Component, Debug, Default)]
|
||||
pub struct Clusters {
|
||||
/// Tile size
|
||||
pub(crate) tile_size: UVec2,
|
||||
pub tile_size: UVec2,
|
||||
/// Number of clusters in `X` / `Y` / `Z` in the view frustum
|
||||
pub(crate) dimensions: UVec3,
|
||||
pub dimensions: UVec3,
|
||||
/// Distance to the far plane of the first depth slice. The first depth slice is special
|
||||
/// and explicitly-configured to avoid having unnecessarily many slices close to the camera.
|
||||
pub(crate) near: f32,
|
||||
pub(crate) far: f32,
|
||||
pub(crate) clusterable_objects: Vec<VisibleClusterableObjects>,
|
||||
pub near: f32,
|
||||
pub far: f32,
|
||||
pub clusterable_objects: Vec<VisibleClusterableObjects>,
|
||||
}
|
||||
|
||||
/// The [`VisibilityClass`] used for clusterables (decals, point lights, directional lights, and spot lights).
|
||||
@ -123,8 +118,8 @@ pub struct ClusterVisibilityClass;
|
||||
|
||||
#[derive(Clone, Component, Debug, Default)]
|
||||
pub struct VisibleClusterableObjects {
|
||||
pub(crate) entities: Vec<Entity>,
|
||||
counts: ClusterableObjectCounts,
|
||||
pub entities: Vec<Entity>,
|
||||
pub counts: ClusterableObjectCounts,
|
||||
}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
@ -137,17 +132,17 @@ pub struct GlobalVisibleClusterableObjects {
|
||||
/// Note that `reflection_probes` and `irradiance_volumes` won't be clustered if
|
||||
/// fewer than 3 SSBOs are available, which usually means on WebGL 2.
|
||||
#[derive(Clone, Copy, Default, Debug)]
|
||||
struct ClusterableObjectCounts {
|
||||
pub struct ClusterableObjectCounts {
|
||||
/// The number of point lights in the cluster.
|
||||
point_lights: u32,
|
||||
pub point_lights: u32,
|
||||
/// The number of spot lights in the cluster.
|
||||
spot_lights: u32,
|
||||
pub spot_lights: u32,
|
||||
/// The number of reflection probes in the cluster.
|
||||
reflection_probes: u32,
|
||||
pub reflection_probes: u32,
|
||||
/// The number of irradiance volumes in the cluster.
|
||||
irradiance_volumes: u32,
|
||||
pub irradiance_volumes: u32,
|
||||
/// The number of decals in the cluster.
|
||||
decals: u32,
|
||||
pub decals: u32,
|
||||
}
|
||||
|
||||
/// An object that projects a decal onto surfaces within its bounds.
|
||||
@ -160,7 +155,7 @@ struct ClusterableObjectCounts {
|
||||
/// but they require bindless textures. This means that they presently can't be
|
||||
/// used on WebGL 2, WebGPU, macOS, or iOS. Bevy's clustered decals can be used
|
||||
/// with forward or deferred rendering and don't require a prepass.
|
||||
#[derive(Component, Debug, Clone, Reflect, ExtractComponent)]
|
||||
#[derive(Component, Debug, Clone, Reflect)]
|
||||
#[reflect(Component, Debug, Clone)]
|
||||
#[require(Transform, Visibility, VisibilityClass)]
|
||||
#[component(on_add = visibility::add_visibility_class::<ClusterVisibilityClass>)]
|
@ -1,6 +1,6 @@
|
||||
use bevy_math::UVec2;
|
||||
|
||||
use crate::{ClusterConfig, Clusters};
|
||||
use super::{ClusterConfig, Clusters};
|
||||
|
||||
fn test_cluster_tiling(config: ClusterConfig, screen_size: UVec2) -> Clusters {
|
||||
let dims = config.dimensions_for_screen_size(screen_size);
|
@ -10,8 +10,9 @@ use bevy_image::Image;
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_transform::components::Transform;
|
||||
|
||||
use super::{cascade::CascadeShadowConfig, light_consts, Cascades};
|
||||
use crate::cluster::ClusterVisibilityClass;
|
||||
use super::{
|
||||
cascade::CascadeShadowConfig, cluster::ClusterVisibilityClass, light_consts, Cascades,
|
||||
};
|
||||
|
||||
/// A Directional light.
|
||||
///
|
||||
@ -172,7 +173,7 @@ pub struct DirectionalLightTexture {
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_app::prelude::*;
|
||||
/// # use bevy_pbr::DirectionalLightShadowMap;
|
||||
/// # use bevy_light::DirectionalLightShadowMap;
|
||||
/// App::new()
|
||||
/// .insert_resource(DirectionalLightShadowMap { size: 4096 });
|
||||
/// ```
|
@ -1,3 +1,5 @@
|
||||
#![expect(missing_docs, reason = "Not all docs are written yet, see #3492.")]
|
||||
|
||||
use bevy_app::{App, Plugin, PostUpdate};
|
||||
use bevy_camera::{
|
||||
primitives::{Aabb, CascadesFrusta, CubemapFrusta, Frustum, Sphere},
|
||||
@ -10,21 +12,27 @@ use bevy_camera::{
|
||||
};
|
||||
use bevy_ecs::{entity::EntityHashSet, prelude::*};
|
||||
use bevy_math::Vec3A;
|
||||
use bevy_mesh::Mesh3d;
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_render::{extract_component::ExtractComponent, mesh::Mesh3d};
|
||||
use bevy_transform::{components::GlobalTransform, TransformSystems};
|
||||
use bevy_utils::Parallel;
|
||||
use core::ops::DerefMut;
|
||||
|
||||
use crate::cluster::{add_clusters, assign_objects_to_clusters, VisibleClusterableObjects};
|
||||
|
||||
pub mod cluster;
|
||||
pub use cluster::ClusteredDecal;
|
||||
use cluster::{
|
||||
add_clusters, assign::assign_objects_to_clusters, ClusterConfig,
|
||||
GlobalVisibleClusterableObjects, VisibleClusterableObjects,
|
||||
};
|
||||
mod ambient_light;
|
||||
pub use ambient_light::AmbientLight;
|
||||
mod probe;
|
||||
pub use probe::{EnvironmentMapLight, LightProbe};
|
||||
mod volumetric;
|
||||
pub use volumetric::{FogVolume, VolumetricFog, VolumetricLight};
|
||||
pub mod cascade;
|
||||
use cascade::{
|
||||
build_directional_light_cascades, clear_directional_light_cascades, CascadeShadowConfig,
|
||||
Cascades,
|
||||
};
|
||||
use cascade::{build_directional_light_cascades, clear_directional_light_cascades};
|
||||
pub use cascade::{CascadeShadowConfig, CascadeShadowConfigBuilder, Cascades};
|
||||
mod point_light;
|
||||
pub use point_light::{
|
||||
update_point_light_frusta, PointLight, PointLightShadowMap, PointLightTexture,
|
||||
@ -111,9 +119,15 @@ impl Plugin for LightPlugin {
|
||||
.register_type::<NotShadowCaster>()
|
||||
.register_type::<NotShadowReceiver>()
|
||||
.register_type::<PointLight>()
|
||||
.register_type::<LightProbe>()
|
||||
.register_type::<EnvironmentMapLight>()
|
||||
.register_type::<VolumetricFog>()
|
||||
.register_type::<VolumetricLight>()
|
||||
.register_type::<PointLightShadowMap>()
|
||||
.register_type::<SpotLight>()
|
||||
.register_type::<ShadowFilteringMethod>()
|
||||
.register_type::<ClusterConfig>()
|
||||
.init_resource::<GlobalVisibleClusterableObjects>()
|
||||
.init_resource::<AmbientLight>()
|
||||
.init_resource::<DirectionalLightShadowMap>()
|
||||
.init_resource::<PointLightShadowMap>()
|
||||
@ -182,7 +196,7 @@ impl Plugin for LightPlugin {
|
||||
}
|
||||
|
||||
/// A convenient alias for `Or<(With<PointLight>, With<SpotLight>,
|
||||
/// With<DirectionalLight>)>`, for use with [`bevy_render::view::VisibleEntities`].
|
||||
/// With<DirectionalLight>)>`, for use with [`bevy_camera::visibility::VisibleEntities`].
|
||||
pub type WithLight = Or<(With<PointLight>, With<SpotLight>, With<DirectionalLight>)>;
|
||||
|
||||
/// Add this component to make a [`Mesh3d`] not cast shadows.
|
||||
@ -197,10 +211,10 @@ pub struct NotShadowCaster;
|
||||
#[derive(Debug, Component, Reflect, Default)]
|
||||
#[reflect(Component, Default, Debug)]
|
||||
pub struct NotShadowReceiver;
|
||||
/// Add this component to make a [`Mesh3d`] using a PBR material with [`diffuse_transmission`](crate::pbr_material::StandardMaterial::diffuse_transmission)`> 0.0`
|
||||
/// Add this component to make a [`Mesh3d`] using a PBR material with `StandardMaterial::diffuse_transmission > 0.0`
|
||||
/// receive shadows on its diffuse transmission lobe. (i.e. its “backside”)
|
||||
///
|
||||
/// Not enabled by default, as it requires carefully setting up [`thickness`](crate::pbr_material::StandardMaterial::thickness)
|
||||
/// Not enabled by default, as it requires carefully setting up `StandardMaterial::thickness`
|
||||
/// (and potentially even baking a thickness texture!) to match the geometry of the mesh, in order to avoid self-shadow artifacts.
|
||||
///
|
||||
/// **Note:** Using [`NotShadowReceiver`] overrides this component.
|
||||
@ -208,12 +222,12 @@ pub struct NotShadowReceiver;
|
||||
#[reflect(Component, Default, Debug)]
|
||||
pub struct TransmittedShadowReceiver;
|
||||
|
||||
/// Add this component to a [`Camera3d`](bevy_core_pipeline::core_3d::Camera3d)
|
||||
/// Add this component to a [`Camera3d`](bevy_camera::Camera3d)
|
||||
/// to control how to anti-alias shadow edges.
|
||||
///
|
||||
/// The different modes use different approaches to
|
||||
/// [Percentage Closer Filtering](https://developer.nvidia.com/gpugems/gpugems/part-ii-lighting-and-shadows/chapter-11-shadow-map-antialiasing).
|
||||
#[derive(Debug, Component, ExtractComponent, Reflect, Clone, Copy, PartialEq, Eq, Default)]
|
||||
#[derive(Debug, Component, Reflect, Clone, Copy, PartialEq, Eq, Default)]
|
||||
#[reflect(Component, Default, Debug, PartialEq, Clone)]
|
||||
pub enum ShadowFilteringMethod {
|
||||
/// Hardware 2x2.
|
@ -166,7 +166,7 @@ pub struct PointLightTexture {
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_app::prelude::*;
|
||||
/// # use bevy_pbr::PointLightShadowMap;
|
||||
/// # use bevy_light::PointLightShadowMap;
|
||||
/// App::new()
|
||||
/// .insert_resource(PointLightShadowMap { size: 2048 });
|
||||
/// ```
|
109
crates/bevy_light/src/probe.rs
Normal file
109
crates/bevy_light/src/probe.rs
Normal file
@ -0,0 +1,109 @@
|
||||
use bevy_asset::Handle;
|
||||
use bevy_camera::visibility::Visibility;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_image::Image;
|
||||
use bevy_math::Quat;
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_transform::components::Transform;
|
||||
|
||||
/// A marker component for a light probe, which is a cuboid region that provides
|
||||
/// global illumination to all fragments inside it.
|
||||
///
|
||||
/// Note that a light probe will have no effect unless the entity contains some
|
||||
/// kind of illumination, which can either be an [`EnvironmentMapLight`] or an
|
||||
/// `IrradianceVolume`.
|
||||
///
|
||||
/// The light probe range is conceptually a unit cube (1×1×1) centered on the
|
||||
/// origin. The [`Transform`] applied to this entity can scale, rotate, or translate
|
||||
/// that cube so that it contains all fragments that should take this light probe into account.
|
||||
///
|
||||
/// When multiple sources of indirect illumination can be applied to a fragment,
|
||||
/// the highest-quality one is chosen. Diffuse and specular illumination are
|
||||
/// considered separately, so, for example, Bevy may decide to sample the
|
||||
/// diffuse illumination from an irradiance volume and the specular illumination
|
||||
/// from a reflection probe. From highest priority to lowest priority, the
|
||||
/// ranking is as follows:
|
||||
///
|
||||
/// | Rank | Diffuse | Specular |
|
||||
/// | ---- | -------------------- | -------------------- |
|
||||
/// | 1 | Lightmap | Lightmap |
|
||||
/// | 2 | Irradiance volume | Reflection probe |
|
||||
/// | 3 | Reflection probe | View environment map |
|
||||
/// | 4 | View environment map | |
|
||||
///
|
||||
/// Note that ambient light is always added to the diffuse component and does
|
||||
/// not participate in the ranking. That is, ambient light is applied in
|
||||
/// addition to, not instead of, the light sources above.
|
||||
///
|
||||
/// A terminology note: Unfortunately, there is little agreement across game and
|
||||
/// graphics engines as to what to call the various techniques that Bevy groups
|
||||
/// under the term *light probe*. In Bevy, a *light probe* is the generic term
|
||||
/// that encompasses both *reflection probes* and *irradiance volumes*. In
|
||||
/// object-oriented terms, *light probe* is the superclass, and *reflection
|
||||
/// probe* and *irradiance volume* are subclasses. In other engines, you may see
|
||||
/// the term *light probe* refer to an irradiance volume with a single voxel, or
|
||||
/// perhaps some other technique, while in Bevy *light probe* refers not to a
|
||||
/// specific technique but rather to a class of techniques. Developers familiar
|
||||
/// with other engines should be aware of this terminology difference.
|
||||
#[derive(Component, Debug, Clone, Copy, Default, Reflect)]
|
||||
#[reflect(Component, Default, Debug, Clone)]
|
||||
#[require(Transform, Visibility)]
|
||||
pub struct LightProbe;
|
||||
|
||||
impl LightProbe {
|
||||
/// Creates a new light probe component.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
/// A pair of cubemap textures that represent the surroundings of a specific
|
||||
/// area in space.
|
||||
///
|
||||
/// See `bevy_pbr::environment_map` for detailed information.
|
||||
#[derive(Clone, Component, Reflect)]
|
||||
#[reflect(Component, Default, Clone)]
|
||||
pub struct EnvironmentMapLight {
|
||||
/// The blurry image that represents diffuse radiance surrounding a region.
|
||||
pub diffuse_map: Handle<Image>,
|
||||
|
||||
/// The typically-sharper, mipmapped image that represents specular radiance
|
||||
/// surrounding a region.
|
||||
pub specular_map: Handle<Image>,
|
||||
|
||||
/// Scale factor applied to the diffuse and specular light generated by this component.
|
||||
///
|
||||
/// After applying this multiplier, the resulting values should
|
||||
/// be in units of [cd/m^2](https://en.wikipedia.org/wiki/Candela_per_square_metre).
|
||||
///
|
||||
/// See also <https://google.github.io/filament/Filament.html#lighting/imagebasedlights/iblunit>.
|
||||
pub intensity: f32,
|
||||
|
||||
/// World space rotation applied to the environment light cubemaps.
|
||||
/// This is useful for users who require a different axis, such as the Z-axis, to serve
|
||||
/// as the vertical axis.
|
||||
pub rotation: Quat,
|
||||
|
||||
/// Whether the light from this environment map contributes diffuse lighting
|
||||
/// to meshes with lightmaps.
|
||||
///
|
||||
/// Set this to false if your lightmap baking tool bakes the diffuse light
|
||||
/// from this environment light into the lightmaps in order to avoid
|
||||
/// counting the radiance from this environment map twice.
|
||||
///
|
||||
/// By default, this is set to true.
|
||||
pub affects_lightmapped_mesh_diffuse: bool,
|
||||
}
|
||||
|
||||
impl Default for EnvironmentMapLight {
|
||||
fn default() -> Self {
|
||||
EnvironmentMapLight {
|
||||
diffuse_map: Handle::default(),
|
||||
specular_map: Handle::default(),
|
||||
intensity: 0.0,
|
||||
rotation: Quat::IDENTITY,
|
||||
affects_lightmapped_mesh_diffuse: true,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,13 @@
|
||||
use bevy_asset::Handle;
|
||||
use bevy_camera::{
|
||||
primitives::Frustum,
|
||||
visibility::{self, Visibility, VisibilityClass},
|
||||
visibility::{self, Visibility, VisibilityClass, VisibleMeshEntities},
|
||||
};
|
||||
use bevy_color::Color;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_image::Image;
|
||||
use bevy_math::{Mat4, Vec4};
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_render::view::VisibleMeshEntities;
|
||||
use bevy_transform::components::{GlobalTransform, Transform};
|
||||
|
||||
use crate::cluster::{ClusterVisibilityClass, GlobalVisibleClusterableObjects};
|
157
crates/bevy_light/src/volumetric.rs
Normal file
157
crates/bevy_light/src/volumetric.rs
Normal file
@ -0,0 +1,157 @@
|
||||
use bevy_asset::Handle;
|
||||
use bevy_camera::visibility::Visibility;
|
||||
use bevy_color::Color;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_image::Image;
|
||||
use bevy_math::Vec3;
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_transform::components::Transform;
|
||||
|
||||
/// Add this component to a [`DirectionalLight`](crate::DirectionalLight) with a shadow map
|
||||
/// (`shadows_enabled: true`) to make volumetric fog interact with it.
|
||||
///
|
||||
/// This allows the light to generate light shafts/god rays.
|
||||
#[derive(Clone, Copy, Component, Default, Debug, Reflect)]
|
||||
#[reflect(Component, Default, Debug, Clone)]
|
||||
pub struct VolumetricLight;
|
||||
|
||||
/// When placed on a [`bevy_camera::Camera3d`], enables
|
||||
/// volumetric fog and volumetric lighting, also known as light shafts or god
|
||||
/// rays.
|
||||
#[derive(Clone, Copy, Component, Debug, Reflect)]
|
||||
#[reflect(Component, Default, Debug, Clone)]
|
||||
pub struct VolumetricFog {
|
||||
/// Color of the ambient light.
|
||||
///
|
||||
/// This is separate from Bevy's [`AmbientLight`](crate::AmbientLight) because an
|
||||
/// [`EnvironmentMapLight`](crate::EnvironmentMapLight) is
|
||||
/// still considered an ambient light for the purposes of volumetric fog. If you're using a
|
||||
/// [`EnvironmentMapLight`](crate::EnvironmentMapLight), for best results,
|
||||
/// this should be a good approximation of the average color of the environment map.
|
||||
///
|
||||
/// Defaults to white.
|
||||
pub ambient_color: Color,
|
||||
|
||||
/// The brightness of the ambient light.
|
||||
///
|
||||
/// If there's no [`EnvironmentMapLight`](crate::EnvironmentMapLight),
|
||||
/// set this to 0.
|
||||
///
|
||||
/// Defaults to 0.1.
|
||||
pub ambient_intensity: f32,
|
||||
|
||||
/// The maximum distance to offset the ray origin randomly by, in meters.
|
||||
///
|
||||
/// This is intended for use with temporal antialiasing. It helps fog look
|
||||
/// less blocky by varying the start position of the ray, using interleaved
|
||||
/// gradient noise.
|
||||
pub jitter: f32,
|
||||
|
||||
/// The number of raymarching steps to perform.
|
||||
///
|
||||
/// Higher values produce higher-quality results with less banding, but
|
||||
/// reduce performance.
|
||||
///
|
||||
/// The default value is 64.
|
||||
pub step_count: u32,
|
||||
}
|
||||
|
||||
impl Default for VolumetricFog {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
step_count: 64,
|
||||
// Matches `AmbientLight` defaults.
|
||||
ambient_color: Color::WHITE,
|
||||
ambient_intensity: 0.1,
|
||||
jitter: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Component, Debug, Reflect)]
|
||||
#[reflect(Component, Default, Debug, Clone)]
|
||||
#[require(Transform, Visibility)]
|
||||
pub struct FogVolume {
|
||||
/// The color of the fog.
|
||||
///
|
||||
/// Note that the fog must be lit by a [`VolumetricLight`] or ambient light
|
||||
/// in order for this color to appear.
|
||||
///
|
||||
/// Defaults to white.
|
||||
pub fog_color: Color,
|
||||
|
||||
/// The density of fog, which measures how dark the fog is.
|
||||
///
|
||||
/// The default value is 0.1.
|
||||
pub density_factor: f32,
|
||||
|
||||
/// Optional 3D voxel density texture for the fog.
|
||||
pub density_texture: Option<Handle<Image>>,
|
||||
|
||||
/// Configurable offset of the density texture in UVW coordinates.
|
||||
///
|
||||
/// This can be used to scroll a repeating density texture in a direction over time
|
||||
/// to create effects like fog moving in the wind. Make sure to configure the texture
|
||||
/// to use `ImageAddressMode::Repeat` if this is your intention.
|
||||
///
|
||||
/// Has no effect when no density texture is present.
|
||||
///
|
||||
/// The default value is (0, 0, 0).
|
||||
pub density_texture_offset: Vec3,
|
||||
|
||||
/// The absorption coefficient, which measures what fraction of light is
|
||||
/// absorbed by the fog at each step.
|
||||
///
|
||||
/// Increasing this value makes the fog darker.
|
||||
///
|
||||
/// The default value is 0.3.
|
||||
pub absorption: f32,
|
||||
|
||||
/// The scattering coefficient, which measures the fraction of light that's
|
||||
/// scattered toward, and away from, the viewer.
|
||||
///
|
||||
/// The default value is 0.3.
|
||||
pub scattering: f32,
|
||||
|
||||
/// Measures the fraction of light that's scattered *toward* the camera, as
|
||||
/// opposed to *away* from the camera.
|
||||
///
|
||||
/// Increasing this value makes light shafts become more prominent when the
|
||||
/// camera is facing toward their source and less prominent when the camera
|
||||
/// is facing away. Essentially, a high value here means the light shafts
|
||||
/// will fade into view as the camera focuses on them and fade away when the
|
||||
/// camera is pointing away.
|
||||
///
|
||||
/// The default value is 0.8.
|
||||
pub scattering_asymmetry: f32,
|
||||
|
||||
/// Applies a nonphysical color to the light.
|
||||
///
|
||||
/// This can be useful for artistic purposes but is nonphysical.
|
||||
///
|
||||
/// The default value is white.
|
||||
pub light_tint: Color,
|
||||
|
||||
/// Scales the light by a fixed fraction.
|
||||
///
|
||||
/// This can be useful for artistic purposes but is nonphysical.
|
||||
///
|
||||
/// The default value is 1.0, which results in no adjustment.
|
||||
pub light_intensity: f32,
|
||||
}
|
||||
|
||||
impl Default for FogVolume {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
absorption: 0.3,
|
||||
scattering: 0.3,
|
||||
density_factor: 0.1,
|
||||
density_texture: None,
|
||||
density_texture_offset: Vec3::ZERO,
|
||||
scattering_asymmetry: 0.5,
|
||||
fog_color: Color::WHITE,
|
||||
light_tint: Color::WHITE,
|
||||
light_intensity: 1.0,
|
||||
}
|
||||
}
|
||||
}
|
@ -9,12 +9,12 @@ license = "MIT OR Apache-2.0"
|
||||
keywords = ["bevy"]
|
||||
|
||||
[features]
|
||||
webgl = []
|
||||
webgpu = []
|
||||
webgl = ["bevy_light/webgl"]
|
||||
webgpu = ["bevy_light/webgpu"]
|
||||
pbr_transmission_textures = []
|
||||
pbr_multi_layer_material_textures = []
|
||||
pbr_anisotropy_texture = []
|
||||
experimental_pbr_pcss = []
|
||||
experimental_pbr_pcss = ["bevy_light/experimental_pbr_pcss"]
|
||||
pbr_specular_textures = []
|
||||
pbr_clustered_decals = []
|
||||
pbr_light_textures = []
|
||||
@ -40,6 +40,7 @@ bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.17.0-dev" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.17.0-dev" }
|
||||
bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.17.0-dev" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.17.0-dev" }
|
||||
bevy_light = { path = "../bevy_light", version = "0.17.0-dev" }
|
||||
bevy_image = { path = "../bevy_image", version = "0.17.0-dev" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.17.0-dev" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.17.0-dev" }
|
||||
|
@ -2,6 +2,7 @@ use core::num::NonZero;
|
||||
|
||||
use bevy_camera::Camera;
|
||||
use bevy_ecs::{entity::EntityHashMap, prelude::*};
|
||||
use bevy_light::cluster::{ClusterableObjectCounts, Clusters, GlobalClusterSettings};
|
||||
use bevy_math::{uvec4, UVec3, UVec4, Vec4};
|
||||
use bevy_render::{
|
||||
render_resource::{
|
||||
@ -13,7 +14,6 @@ use bevy_render::{
|
||||
};
|
||||
use tracing::warn;
|
||||
|
||||
use super::{ClusterableObjectCounts, Clusters, GlobalClusterSettings};
|
||||
use crate::MeshPipeline;
|
||||
|
||||
// NOTE: this must be kept in sync with the same constants in
|
@ -27,6 +27,8 @@ use bevy_ecs::{
|
||||
system::{Query, Res, ResMut},
|
||||
};
|
||||
use bevy_image::Image;
|
||||
pub use bevy_light::cluster::ClusteredDecal;
|
||||
use bevy_light::{DirectionalLightTexture, PointLightTexture, SpotLightTexture};
|
||||
use bevy_math::Mat4;
|
||||
use bevy_platform::collections::HashMap;
|
||||
pub use bevy_render::primitives::CubemapLayout;
|
||||
@ -47,9 +49,7 @@ use bevy_render::{
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
pub use crate::ClusteredDecal;
|
||||
use crate::{binding_arrays_are_usable, prepare_lights, GlobalClusterableObjectMeta};
|
||||
pub use crate::{DirectionalLightTexture, PointLightTexture, SpotLightTexture};
|
||||
|
||||
/// The maximum number of decals that can be present in a view.
|
||||
///
|
||||
|
@ -1,14 +1,11 @@
|
||||
use crate::{
|
||||
graph::NodePbr, irradiance_volume::IrradianceVolume, prelude::EnvironmentMapLight,
|
||||
MeshPipeline, MeshViewBindGroup, RenderViewLightProbes, ScreenSpaceAmbientOcclusion,
|
||||
ScreenSpaceReflectionsUniform, ViewEnvironmentMapUniformOffset, ViewLightProbesUniformOffset,
|
||||
graph::NodePbr, irradiance_volume::IrradianceVolume, MeshPipeline, MeshViewBindGroup,
|
||||
RenderViewLightProbes, ScreenSpaceAmbientOcclusion, ScreenSpaceReflectionsUniform,
|
||||
ViewEnvironmentMapUniformOffset, ViewLightProbesUniformOffset,
|
||||
ViewScreenSpaceReflectionsUniformOffset, TONEMAPPING_LUT_SAMPLER_BINDING_INDEX,
|
||||
TONEMAPPING_LUT_TEXTURE_BINDING_INDEX,
|
||||
};
|
||||
use crate::{
|
||||
DistanceFog, MeshPipelineKey, ShadowFilteringMethod, ViewFogUniformOffset,
|
||||
ViewLightsUniformOffset,
|
||||
};
|
||||
use crate::{DistanceFog, MeshPipelineKey, ViewFogUniformOffset, ViewLightsUniformOffset};
|
||||
use bevy_app::prelude::*;
|
||||
use bevy_asset::{embedded_asset, load_embedded_asset, Handle};
|
||||
use bevy_core_pipeline::{
|
||||
@ -21,6 +18,7 @@ use bevy_core_pipeline::{
|
||||
};
|
||||
use bevy_ecs::{prelude::*, query::QueryItem};
|
||||
use bevy_image::BevyDefault as _;
|
||||
use bevy_light::{EnvironmentMapLight, ShadowFilteringMethod};
|
||||
use bevy_render::{
|
||||
extract_component::{
|
||||
ComponentUniforms, ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin,
|
||||
|
@ -31,7 +31,6 @@ pub mod decal;
|
||||
pub mod deferred;
|
||||
mod extended_material;
|
||||
mod fog;
|
||||
mod light;
|
||||
mod light_probe;
|
||||
mod lightmap;
|
||||
mod material;
|
||||
@ -48,12 +47,19 @@ mod volumetric_fog;
|
||||
use bevy_color::{Color, LinearRgba};
|
||||
|
||||
pub use atmosphere::*;
|
||||
use bevy_light::SimulationLightSystems;
|
||||
pub use bevy_light::{
|
||||
light_consts, AmbientLight, CascadeShadowConfig, CascadeShadowConfigBuilder, Cascades,
|
||||
ClusteredDecal, DirectionalLight, DirectionalLightShadowMap, DirectionalLightTexture,
|
||||
FogVolume, LightPlugin, LightProbe, NotShadowCaster, NotShadowReceiver, PointLight,
|
||||
PointLightShadowMap, PointLightTexture, ShadowFilteringMethod, SpotLight, SpotLightTexture,
|
||||
TransmittedShadowReceiver, VolumetricFog, VolumetricLight,
|
||||
};
|
||||
pub use cluster::*;
|
||||
pub use components::*;
|
||||
pub use decal::clustered::ClusteredDecalPlugin;
|
||||
pub use extended_material::*;
|
||||
pub use fog::*;
|
||||
pub use light::*;
|
||||
pub use light_probe::*;
|
||||
pub use lightmap::*;
|
||||
pub use material::*;
|
||||
@ -65,7 +71,7 @@ pub use prepass::*;
|
||||
pub use render::*;
|
||||
pub use ssao::*;
|
||||
pub use ssr::*;
|
||||
pub use volumetric_fog::{FogVolume, VolumetricFog, VolumetricFogPlugin, VolumetricLight};
|
||||
pub use volumetric_fog::VolumetricFogPlugin;
|
||||
|
||||
/// The PBR prelude.
|
||||
///
|
||||
@ -74,14 +80,17 @@ pub mod prelude {
|
||||
#[doc(hidden)]
|
||||
pub use crate::{
|
||||
fog::{DistanceFog, FogFalloff},
|
||||
light::{light_consts, AmbientLight, DirectionalLight, PointLight, SpotLight},
|
||||
light_probe::{environment_map::EnvironmentMapLight, LightProbe},
|
||||
material::{Material, MaterialPlugin},
|
||||
mesh_material::MeshMaterial3d,
|
||||
parallax::ParallaxMappingMethod,
|
||||
pbr_material::StandardMaterial,
|
||||
ssao::ScreenSpaceAmbientOcclusionPlugin,
|
||||
};
|
||||
#[doc(hidden)]
|
||||
pub use bevy_light::{
|
||||
light_consts, AmbientLight, DirectionalLight, EnvironmentMapLight, LightProbe, PointLight,
|
||||
SpotLight,
|
||||
};
|
||||
}
|
||||
|
||||
pub mod graph {
|
||||
@ -122,7 +131,6 @@ pub mod graph {
|
||||
}
|
||||
}
|
||||
|
||||
pub use crate::cascade::{CascadeShadowConfig, CascadeShadowConfigBuilder, Cascades};
|
||||
use crate::{deferred::DeferredPbrLightingPlugin, graph::NodePbr};
|
||||
use bevy_app::prelude::*;
|
||||
use bevy_asset::{AssetApp, AssetPath, Assets, Handle};
|
||||
@ -203,8 +211,6 @@ impl Plugin for PbrPlugin {
|
||||
load_shader_library!(app, "meshlet/dummy_visibility_buffer_resolve.wgsl");
|
||||
|
||||
app.register_asset_reflect::<StandardMaterial>()
|
||||
.register_type::<ClusterConfig>()
|
||||
.init_resource::<GlobalVisibleClusterableObjects>()
|
||||
.register_type::<DefaultOpaqueRendererMethod>()
|
||||
.init_resource::<DefaultOpaqueRendererMethod>()
|
||||
.add_plugins((
|
||||
|
@ -44,13 +44,10 @@
|
||||
//!
|
||||
//! [several pre-filtered environment maps]: https://github.com/KhronosGroup/glTF-Sample-Environments
|
||||
|
||||
use bevy_asset::{AssetId, Handle};
|
||||
use bevy_ecs::{
|
||||
component::Component, query::QueryItem, reflect::ReflectComponent, system::lifetimeless::Read,
|
||||
};
|
||||
use bevy_asset::AssetId;
|
||||
use bevy_ecs::{query::QueryItem, system::lifetimeless::Read};
|
||||
use bevy_image::Image;
|
||||
use bevy_math::Quat;
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||
use bevy_light::EnvironmentMapLight;
|
||||
use bevy_render::{
|
||||
extract_instances::ExtractInstance,
|
||||
render_asset::RenderAssets,
|
||||
@ -72,56 +69,6 @@ use crate::{
|
||||
|
||||
use super::{LightProbeComponent, RenderViewLightProbes};
|
||||
|
||||
/// A pair of cubemap textures that represent the surroundings of a specific
|
||||
/// area in space.
|
||||
///
|
||||
/// See [`crate::environment_map`] for detailed information.
|
||||
#[derive(Clone, Component, Reflect)]
|
||||
#[reflect(Component, Default, Clone)]
|
||||
pub struct EnvironmentMapLight {
|
||||
/// The blurry image that represents diffuse radiance surrounding a region.
|
||||
pub diffuse_map: Handle<Image>,
|
||||
|
||||
/// The typically-sharper, mipmapped image that represents specular radiance
|
||||
/// surrounding a region.
|
||||
pub specular_map: Handle<Image>,
|
||||
|
||||
/// Scale factor applied to the diffuse and specular light generated by this component.
|
||||
///
|
||||
/// After applying this multiplier, the resulting values should
|
||||
/// be in units of [cd/m^2](https://en.wikipedia.org/wiki/Candela_per_square_metre).
|
||||
///
|
||||
/// See also <https://google.github.io/filament/Filament.html#lighting/imagebasedlights/iblunit>.
|
||||
pub intensity: f32,
|
||||
|
||||
/// World space rotation applied to the environment light cubemaps.
|
||||
/// This is useful for users who require a different axis, such as the Z-axis, to serve
|
||||
/// as the vertical axis.
|
||||
pub rotation: Quat,
|
||||
|
||||
/// Whether the light from this environment map contributes diffuse lighting
|
||||
/// to meshes with lightmaps.
|
||||
///
|
||||
/// Set this to false if your lightmap baking tool bakes the diffuse light
|
||||
/// from this environment light into the lightmaps in order to avoid
|
||||
/// counting the radiance from this environment map twice.
|
||||
///
|
||||
/// By default, this is set to true.
|
||||
pub affects_lightmapped_mesh_diffuse: bool,
|
||||
}
|
||||
|
||||
impl Default for EnvironmentMapLight {
|
||||
fn default() -> Self {
|
||||
EnvironmentMapLight {
|
||||
diffuse_map: Handle::default(),
|
||||
specular_map: Handle::default(),
|
||||
intensity: 0.0,
|
||||
rotation: Quat::IDENTITY,
|
||||
affects_lightmapped_mesh_diffuse: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Like [`EnvironmentMapLight`], but contains asset IDs instead of handles.
|
||||
///
|
||||
/// This is for use in the render app.
|
||||
|
@ -135,6 +135,7 @@
|
||||
|
||||
use bevy_ecs::{component::Component, reflect::ReflectComponent};
|
||||
use bevy_image::Image;
|
||||
use bevy_light::LightProbe;
|
||||
use bevy_render::{
|
||||
render_asset::RenderAssets,
|
||||
render_resource::{
|
||||
@ -155,7 +156,7 @@ use crate::{
|
||||
MAX_VIEW_LIGHT_PROBES,
|
||||
};
|
||||
|
||||
use super::{LightProbe, LightProbeComponent};
|
||||
use super::LightProbeComponent;
|
||||
|
||||
/// On WebGL and WebGPU, we must disable irradiance volumes, as otherwise we can
|
||||
/// overflow the number of texture bindings when deferred rendering is in use
|
||||
|
@ -8,15 +8,14 @@ use bevy_ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
query::With,
|
||||
reflect::ReflectComponent,
|
||||
resource::Resource,
|
||||
schedule::IntoScheduleConfigs,
|
||||
system::{Commands, Local, Query, Res, ResMut},
|
||||
};
|
||||
use bevy_image::Image;
|
||||
use bevy_light::{EnvironmentMapLight, LightProbe};
|
||||
use bevy_math::{Affine3A, FloatOrd, Mat4, Vec3A, Vec4};
|
||||
use bevy_platform::collections::HashMap;
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||
use bevy_render::{
|
||||
extract_instances::ExtractInstancesPlugin,
|
||||
load_shader_library,
|
||||
@ -27,7 +26,7 @@ use bevy_render::{
|
||||
settings::WgpuFeatures,
|
||||
sync_world::RenderEntity,
|
||||
texture::{FallbackImage, GpuImage},
|
||||
view::{ExtractedView, Visibility},
|
||||
view::ExtractedView,
|
||||
Extract, ExtractSchedule, Render, RenderApp, RenderSystems,
|
||||
};
|
||||
use bevy_transform::{components::Transform, prelude::GlobalTransform};
|
||||
@ -35,7 +34,7 @@ use tracing::error;
|
||||
|
||||
use core::{hash::Hash, ops::Deref};
|
||||
|
||||
use crate::light_probe::environment_map::{EnvironmentMapIds, EnvironmentMapLight};
|
||||
use crate::light_probe::environment_map::EnvironmentMapIds;
|
||||
|
||||
use self::irradiance_volume::IrradianceVolume;
|
||||
|
||||
@ -59,50 +58,6 @@ const STANDARD_MATERIAL_FRAGMENT_SHADER_MIN_TEXTURE_BINDINGS: usize = 16;
|
||||
/// cubemaps applied to all objects that a view renders.
|
||||
pub struct LightProbePlugin;
|
||||
|
||||
/// A marker component for a light probe, which is a cuboid region that provides
|
||||
/// global illumination to all fragments inside it.
|
||||
///
|
||||
/// Note that a light probe will have no effect unless the entity contains some
|
||||
/// kind of illumination, which can either be an [`EnvironmentMapLight`] or an
|
||||
/// [`IrradianceVolume`].
|
||||
///
|
||||
/// The light probe range is conceptually a unit cube (1×1×1) centered on the
|
||||
/// origin. The [`Transform`] applied to this entity can scale, rotate, or translate
|
||||
/// that cube so that it contains all fragments that should take this light probe into account.
|
||||
///
|
||||
/// When multiple sources of indirect illumination can be applied to a fragment,
|
||||
/// the highest-quality one is chosen. Diffuse and specular illumination are
|
||||
/// considered separately, so, for example, Bevy may decide to sample the
|
||||
/// diffuse illumination from an irradiance volume and the specular illumination
|
||||
/// from a reflection probe. From highest priority to lowest priority, the
|
||||
/// ranking is as follows:
|
||||
///
|
||||
/// | Rank | Diffuse | Specular |
|
||||
/// | ---- | -------------------- | -------------------- |
|
||||
/// | 1 | Lightmap | Lightmap |
|
||||
/// | 2 | Irradiance volume | Reflection probe |
|
||||
/// | 3 | Reflection probe | View environment map |
|
||||
/// | 4 | View environment map | |
|
||||
///
|
||||
/// Note that ambient light is always added to the diffuse component and does
|
||||
/// not participate in the ranking. That is, ambient light is applied in
|
||||
/// addition to, not instead of, the light sources above.
|
||||
///
|
||||
/// A terminology note: Unfortunately, there is little agreement across game and
|
||||
/// graphics engines as to what to call the various techniques that Bevy groups
|
||||
/// under the term *light probe*. In Bevy, a *light probe* is the generic term
|
||||
/// that encompasses both *reflection probes* and *irradiance volumes*. In
|
||||
/// object-oriented terms, *light probe* is the superclass, and *reflection
|
||||
/// probe* and *irradiance volume* are subclasses. In other engines, you may see
|
||||
/// the term *light probe* refer to an irradiance volume with a single voxel, or
|
||||
/// perhaps some other technique, while in Bevy *light probe* refers not to a
|
||||
/// specific technique but rather to a class of techniques. Developers familiar
|
||||
/// with other engines should be aware of this terminology difference.
|
||||
#[derive(Component, Debug, Clone, Copy, Default, Reflect)]
|
||||
#[reflect(Component, Default, Debug, Clone)]
|
||||
#[require(Transform, Visibility)]
|
||||
pub struct LightProbe;
|
||||
|
||||
/// A GPU type that stores information about a light probe.
|
||||
#[derive(Clone, Copy, ShaderType, Default)]
|
||||
struct RenderLightProbe {
|
||||
@ -302,14 +257,6 @@ pub trait LightProbeComponent: Send + Sync + Component + Sized {
|
||||
) -> RenderViewLightProbes<Self>;
|
||||
}
|
||||
|
||||
impl LightProbe {
|
||||
/// Creates a new light probe component.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
/// The uniform struct extracted from [`EnvironmentMapLight`].
|
||||
/// Will be available for use in the Environment Map shader.
|
||||
#[derive(Component, ShaderType, Clone)]
|
||||
@ -341,9 +288,7 @@ impl Plugin for LightProbePlugin {
|
||||
load_shader_library!(app, "environment_map.wgsl");
|
||||
load_shader_library!(app, "irradiance_volume.wgsl");
|
||||
|
||||
app.register_type::<LightProbe>()
|
||||
.register_type::<EnvironmentMapLight>()
|
||||
.register_type::<IrradianceVolume>()
|
||||
app.register_type::<IrradianceVolume>()
|
||||
.add_plugins(ExtractInstancesPlugin::<EnvironmentMapIds>::new());
|
||||
}
|
||||
|
||||
|
@ -2,13 +2,14 @@ use super::{
|
||||
instance_manager::InstanceManager, pipelines::MeshletPipelines,
|
||||
resource_manager::ResourceManager,
|
||||
};
|
||||
use crate::{environment_map::EnvironmentMapLight, irradiance_volume::IrradianceVolume, *};
|
||||
use crate::{irradiance_volume::IrradianceVolume, *};
|
||||
use bevy_core_pipeline::{
|
||||
core_3d::Camera3d,
|
||||
prepass::{DeferredPrepass, DepthPrepass, MotionVectorPrepass, NormalPrepass},
|
||||
tonemapping::{DebandDither, Tonemapping},
|
||||
};
|
||||
use bevy_derive::{Deref, DerefMut};
|
||||
use bevy_light::EnvironmentMapLight;
|
||||
use bevy_platform::collections::{HashMap, HashSet};
|
||||
use bevy_render::erased_render_asset::ErasedRenderAssets;
|
||||
use bevy_render::{
|
||||
|
@ -1,6 +1,3 @@
|
||||
use self::assign::ClusterableObjectType;
|
||||
use crate::assign::calculate_cluster_factors;
|
||||
use crate::cascade::{Cascade, CascadeShadowConfig, Cascades};
|
||||
use crate::*;
|
||||
use bevy_asset::UntypedAssetId;
|
||||
pub use bevy_camera::primitives::{face_index_to_name, CubeMapFace, CUBE_MAP_FACES};
|
||||
@ -14,6 +11,13 @@ use bevy_ecs::{
|
||||
prelude::*,
|
||||
system::lifetimeless::Read,
|
||||
};
|
||||
use bevy_light::cascade::Cascade;
|
||||
use bevy_light::cluster::assign::{calculate_cluster_factors, ClusterableObjectType};
|
||||
use bevy_light::cluster::GlobalVisibleClusterableObjects;
|
||||
use bevy_light::{
|
||||
spot_light_clip_from_view, spot_light_world_from_view, DirectionalLightShadowMap,
|
||||
NotShadowCaster, PointLightShadowMap,
|
||||
};
|
||||
use bevy_math::{ops, Mat4, UVec4, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles};
|
||||
use bevy_platform::collections::{HashMap, HashSet};
|
||||
use bevy_platform::hash::FixedHasher;
|
||||
@ -798,7 +802,7 @@ pub fn prepare_lights(
|
||||
// - then by entity as a stable key to ensure that a consistent set of lights are chosen if the light count limit is exceeded.
|
||||
point_lights.sort_by_cached_key(|(entity, _, light, _)| {
|
||||
(
|
||||
ClusterableObjectType::from_point_or_spot_light(light).ordering(),
|
||||
point_or_spot_light_to_clusterable(light).ordering(),
|
||||
*entity,
|
||||
)
|
||||
});
|
||||
@ -2265,3 +2269,18 @@ impl ShadowPassNode {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates the [`ClusterableObjectType`] data for a point or spot light.
|
||||
fn point_or_spot_light_to_clusterable(point_light: &ExtractedPointLight) -> ClusterableObjectType {
|
||||
match point_light.spot_light_angles {
|
||||
Some((_, outer_angle)) => ClusterableObjectType::SpotLight {
|
||||
outer_angle,
|
||||
shadows_enabled: point_light.shadows_enabled,
|
||||
volumetric: point_light.volumetric,
|
||||
},
|
||||
None => ClusterableObjectType::PointLight {
|
||||
shadows_enabled: point_light.shadows_enabled,
|
||||
volumetric: point_light.volumetric,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,9 @@ use bevy_ecs::{
|
||||
system::{lifetimeless::*, SystemParamItem, SystemState},
|
||||
};
|
||||
use bevy_image::{BevyDefault, ImageSampler, TextureFormatPixelInfo};
|
||||
use bevy_light::{
|
||||
EnvironmentMapLight, NotShadowCaster, NotShadowReceiver, TransmittedShadowReceiver,
|
||||
};
|
||||
use bevy_math::{Affine3, Rect, UVec2, Vec3, Vec4};
|
||||
use bevy_platform::collections::{hash_map::Entry, HashMap};
|
||||
use bevy_render::{
|
||||
@ -52,7 +55,6 @@ use material_bind_groups::MaterialBindingId;
|
||||
use tracing::{error, warn};
|
||||
|
||||
use self::irradiance_volume::IRRADIANCE_VOLUMES_ARE_USABLE;
|
||||
use crate::environment_map::EnvironmentMapLight;
|
||||
use crate::irradiance_volume::IrradianceVolume;
|
||||
use crate::{
|
||||
render::{
|
||||
|
@ -17,6 +17,7 @@ use bevy_ecs::{
|
||||
world::{FromWorld, World},
|
||||
};
|
||||
use bevy_image::BevyDefault as _;
|
||||
use bevy_light::EnvironmentMapLight;
|
||||
use bevy_math::Vec4;
|
||||
use bevy_render::{
|
||||
globals::{GlobalsBuffer, GlobalsUniform},
|
||||
@ -30,7 +31,6 @@ use bevy_render::{
|
||||
},
|
||||
};
|
||||
use core::{array, num::NonZero};
|
||||
use environment_map::EnvironmentMapLight;
|
||||
|
||||
use crate::{
|
||||
decal::{
|
||||
|
@ -6,14 +6,14 @@
|
||||
//! for light beams from directional lights to shine through, creating what is
|
||||
//! known as *light shafts* or *god rays*.
|
||||
//!
|
||||
//! To add volumetric fog to a scene, add [`VolumetricFog`] to the
|
||||
//! camera, and add [`VolumetricLight`] to directional lights that you wish to
|
||||
//! be volumetric. [`VolumetricFog`] feature numerous settings that
|
||||
//! To add volumetric fog to a scene, add [`crate::VolumetricFog`] to the
|
||||
//! camera, and add [`crate::VolumetricLight`] to directional lights that you wish to
|
||||
//! be volumetric. [`crate::VolumetricFog`] feature numerous settings that
|
||||
//! allow you to define the accuracy of the simulation, as well as the look of
|
||||
//! the fog. Currently, only interaction with directional lights that have
|
||||
//! shadow maps is supported. Note that the overhead of the effect scales
|
||||
//! directly with the number of directional lights in use, so apply
|
||||
//! [`VolumetricLight`] sparingly for the best results.
|
||||
//! [`crate::VolumetricLight`] sparingly for the best results.
|
||||
//!
|
||||
//! The overall algorithm, which is implemented as a postprocessing effect, is a
|
||||
//! combination of the techniques described in [Scratchapixel] and [this blog
|
||||
@ -30,30 +30,24 @@
|
||||
//! [Henyey-Greenstein phase function]: https://www.pbr-book.org/4ed/Volume_Scattering/Phase_Functions#TheHenyeyndashGreensteinPhaseFunction
|
||||
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_asset::{embedded_asset, Assets, Handle};
|
||||
use bevy_color::Color;
|
||||
use bevy_asset::{embedded_asset, Assets};
|
||||
use bevy_core_pipeline::core_3d::{
|
||||
graph::{Core3d, Node3d},
|
||||
prepare_core_3d_depth_textures,
|
||||
};
|
||||
use bevy_ecs::{
|
||||
component::Component, reflect::ReflectComponent, schedule::IntoScheduleConfigs as _,
|
||||
};
|
||||
use bevy_image::Image;
|
||||
use bevy_ecs::schedule::IntoScheduleConfigs as _;
|
||||
use bevy_light::FogVolume;
|
||||
use bevy_math::{
|
||||
primitives::{Cuboid, Plane3d},
|
||||
Vec2, Vec3,
|
||||
};
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||
use bevy_render::{
|
||||
mesh::{Mesh, Meshable},
|
||||
render_graph::{RenderGraphExt, ViewNodeRunner},
|
||||
render_resource::SpecializedRenderPipelines,
|
||||
sync_component::SyncComponentPlugin,
|
||||
view::Visibility,
|
||||
ExtractSchedule, Render, RenderApp, RenderSystems,
|
||||
};
|
||||
use bevy_transform::components::Transform;
|
||||
use render::{
|
||||
VolumetricFogNode, VolumetricFogPipeline, VolumetricFogUniformBuffer, CUBE_MESH, PLANE_MESH,
|
||||
};
|
||||
@ -65,127 +59,6 @@ pub mod render;
|
||||
/// A plugin that implements volumetric fog.
|
||||
pub struct VolumetricFogPlugin;
|
||||
|
||||
/// Add this component to a [`DirectionalLight`](crate::DirectionalLight) with a shadow map
|
||||
/// (`shadows_enabled: true`) to make volumetric fog interact with it.
|
||||
///
|
||||
/// This allows the light to generate light shafts/god rays.
|
||||
#[derive(Clone, Copy, Component, Default, Debug, Reflect)]
|
||||
#[reflect(Component, Default, Debug, Clone)]
|
||||
pub struct VolumetricLight;
|
||||
|
||||
/// When placed on a [`bevy_core_pipeline::core_3d::Camera3d`], enables
|
||||
/// volumetric fog and volumetric lighting, also known as light shafts or god
|
||||
/// rays.
|
||||
#[derive(Clone, Copy, Component, Debug, Reflect)]
|
||||
#[reflect(Component, Default, Debug, Clone)]
|
||||
pub struct VolumetricFog {
|
||||
/// Color of the ambient light.
|
||||
///
|
||||
/// This is separate from Bevy's [`AmbientLight`](crate::light::AmbientLight) because an
|
||||
/// [`EnvironmentMapLight`](crate::environment_map::EnvironmentMapLight) is
|
||||
/// still considered an ambient light for the purposes of volumetric fog. If you're using a
|
||||
/// [`EnvironmentMapLight`](crate::environment_map::EnvironmentMapLight), for best results,
|
||||
/// this should be a good approximation of the average color of the environment map.
|
||||
///
|
||||
/// Defaults to white.
|
||||
pub ambient_color: Color,
|
||||
|
||||
/// The brightness of the ambient light.
|
||||
///
|
||||
/// If there's no [`EnvironmentMapLight`](crate::environment_map::EnvironmentMapLight),
|
||||
/// set this to 0.
|
||||
///
|
||||
/// Defaults to 0.1.
|
||||
pub ambient_intensity: f32,
|
||||
|
||||
/// The maximum distance to offset the ray origin randomly by, in meters.
|
||||
///
|
||||
/// This is intended for use with temporal antialiasing. It helps fog look
|
||||
/// less blocky by varying the start position of the ray, using interleaved
|
||||
/// gradient noise.
|
||||
pub jitter: f32,
|
||||
|
||||
/// The number of raymarching steps to perform.
|
||||
///
|
||||
/// Higher values produce higher-quality results with less banding, but
|
||||
/// reduce performance.
|
||||
///
|
||||
/// The default value is 64.
|
||||
pub step_count: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Component, Debug, Reflect)]
|
||||
#[reflect(Component, Default, Debug, Clone)]
|
||||
#[require(Transform, Visibility)]
|
||||
pub struct FogVolume {
|
||||
/// The color of the fog.
|
||||
///
|
||||
/// Note that the fog must be lit by a [`VolumetricLight`] or ambient light
|
||||
/// in order for this color to appear.
|
||||
///
|
||||
/// Defaults to white.
|
||||
pub fog_color: Color,
|
||||
|
||||
/// The density of fog, which measures how dark the fog is.
|
||||
///
|
||||
/// The default value is 0.1.
|
||||
pub density_factor: f32,
|
||||
|
||||
/// Optional 3D voxel density texture for the fog.
|
||||
pub density_texture: Option<Handle<Image>>,
|
||||
|
||||
/// Configurable offset of the density texture in UVW coordinates.
|
||||
///
|
||||
/// This can be used to scroll a repeating density texture in a direction over time
|
||||
/// to create effects like fog moving in the wind. Make sure to configure the texture
|
||||
/// to use `ImageAddressMode::Repeat` if this is your intention.
|
||||
///
|
||||
/// Has no effect when no density texture is present.
|
||||
///
|
||||
/// The default value is (0, 0, 0).
|
||||
pub density_texture_offset: Vec3,
|
||||
|
||||
/// The absorption coefficient, which measures what fraction of light is
|
||||
/// absorbed by the fog at each step.
|
||||
///
|
||||
/// Increasing this value makes the fog darker.
|
||||
///
|
||||
/// The default value is 0.3.
|
||||
pub absorption: f32,
|
||||
|
||||
/// The scattering coefficient, which measures the fraction of light that's
|
||||
/// scattered toward, and away from, the viewer.
|
||||
///
|
||||
/// The default value is 0.3.
|
||||
pub scattering: f32,
|
||||
|
||||
/// Measures the fraction of light that's scattered *toward* the camera, as
|
||||
/// opposed to *away* from the camera.
|
||||
///
|
||||
/// Increasing this value makes light shafts become more prominent when the
|
||||
/// camera is facing toward their source and less prominent when the camera
|
||||
/// is facing away. Essentially, a high value here means the light shafts
|
||||
/// will fade into view as the camera focuses on them and fade away when the
|
||||
/// camera is pointing away.
|
||||
///
|
||||
/// The default value is 0.8.
|
||||
pub scattering_asymmetry: f32,
|
||||
|
||||
/// Applies a nonphysical color to the light.
|
||||
///
|
||||
/// This can be useful for artistic purposes but is nonphysical.
|
||||
///
|
||||
/// The default value is white.
|
||||
pub light_tint: Color,
|
||||
|
||||
/// Scales the light by a fixed fraction.
|
||||
///
|
||||
/// This can be useful for artistic purposes but is nonphysical.
|
||||
///
|
||||
/// The default value is 1.0, which results in no adjustment.
|
||||
pub light_intensity: f32,
|
||||
}
|
||||
|
||||
impl Plugin for VolumetricFogPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
embedded_asset!(app, "volumetric_fog.wgsl");
|
||||
@ -194,9 +67,6 @@ impl Plugin for VolumetricFogPlugin {
|
||||
meshes.insert(&PLANE_MESH, Plane3d::new(Vec3::Z, Vec2::ONE).mesh().into());
|
||||
meshes.insert(&CUBE_MESH, Cuboid::new(1.0, 1.0, 1.0).mesh().into());
|
||||
|
||||
app.register_type::<VolumetricFog>()
|
||||
.register_type::<VolumetricLight>();
|
||||
|
||||
app.add_plugins(SyncComponentPlugin::<FogVolume>::default());
|
||||
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
@ -238,31 +108,3 @@ impl Plugin for VolumetricFogPlugin {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for VolumetricFog {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
step_count: 64,
|
||||
// Matches `AmbientLight` defaults.
|
||||
ambient_color: Color::WHITE,
|
||||
ambient_intensity: 0.1,
|
||||
jitter: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FogVolume {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
absorption: 0.3,
|
||||
scattering: 0.3,
|
||||
density_factor: 0.1,
|
||||
density_texture: None,
|
||||
density_texture_offset: Vec3::ZERO,
|
||||
scattering_asymmetry: 0.5,
|
||||
fog_color: Color::WHITE,
|
||||
light_tint: Color::WHITE,
|
||||
light_intensity: 1.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,7 @@ bevy_tasks = { path = "../bevy_tasks", version = "0.17.0-dev" }
|
||||
bevy_image = { path = "../bevy_image", version = "0.17.0-dev" }
|
||||
bevy_mesh = { path = "../bevy_mesh", version = "0.17.0-dev" }
|
||||
bevy_camera = { path = "../bevy_camera", version = "0.17.0-dev" }
|
||||
bevy_light = { path = "../bevy_light", version = "0.17.0-dev" }
|
||||
bevy_platform = { path = "../bevy_platform", version = "0.17.0-dev", default-features = false, features = [
|
||||
"std",
|
||||
"serialize",
|
||||
|
41
crates/bevy_render/src/extract_impls.rs
Normal file
41
crates/bevy_render/src/extract_impls.rs
Normal file
@ -0,0 +1,41 @@
|
||||
//! This module exists because of the orphan rule
|
||||
|
||||
use bevy_ecs::query::QueryItem;
|
||||
use bevy_light::{cluster::ClusteredDecal, AmbientLight, ShadowFilteringMethod};
|
||||
|
||||
use crate::{extract_component::ExtractComponent, extract_resource::ExtractResource};
|
||||
|
||||
impl ExtractComponent for ClusteredDecal {
|
||||
type QueryData = &'static Self;
|
||||
type QueryFilter = ();
|
||||
type Out = Self;
|
||||
|
||||
fn extract_component(item: QueryItem<Self::QueryData>) -> Option<Self::Out> {
|
||||
Some(item.clone())
|
||||
}
|
||||
}
|
||||
impl ExtractResource for AmbientLight {
|
||||
type Source = Self;
|
||||
|
||||
fn extract_resource(source: &Self::Source) -> Self {
|
||||
source.clone()
|
||||
}
|
||||
}
|
||||
impl ExtractComponent for AmbientLight {
|
||||
type QueryData = &'static Self;
|
||||
type QueryFilter = ();
|
||||
type Out = Self;
|
||||
|
||||
fn extract_component(item: QueryItem<Self::QueryData>) -> Option<Self::Out> {
|
||||
Some(item.clone())
|
||||
}
|
||||
}
|
||||
impl ExtractComponent for ShadowFilteringMethod {
|
||||
type QueryData = &'static Self;
|
||||
type QueryFilter = ();
|
||||
type Out = Self;
|
||||
|
||||
fn extract_component(item: QueryItem<Self::QueryData>) -> Option<Self::Out> {
|
||||
Some(*item)
|
||||
}
|
||||
}
|
@ -50,6 +50,7 @@ pub mod sync_world;
|
||||
pub mod texture;
|
||||
pub mod view;
|
||||
pub use bevy_camera::primitives;
|
||||
mod extract_impls;
|
||||
|
||||
/// The render prelude.
|
||||
///
|
||||
|
@ -6,13 +6,7 @@ use std::fmt::{self, Formatter};
|
||||
use bevy::{
|
||||
color::palettes::css::{SILVER, YELLOW},
|
||||
input::mouse::AccumulatedMouseMotion,
|
||||
pbr::{
|
||||
decal::{
|
||||
self,
|
||||
clustered::{DirectionalLightTexture, PointLightTexture, SpotLightTexture},
|
||||
},
|
||||
NotShadowCaster,
|
||||
},
|
||||
pbr::{decal, DirectionalLightTexture, NotShadowCaster, PointLightTexture, SpotLightTexture},
|
||||
prelude::*,
|
||||
render::renderer::{RenderAdapter, RenderDevice},
|
||||
window::SystemCursorIcon,
|
||||
|
@ -1,8 +1,8 @@
|
||||
diff --git a/crates/bevy_pbr/src/cluster/mod.rs b/crates/bevy_pbr/src/cluster/mod.rs
|
||||
index a8c218b44..13cc9f9c6 100644
|
||||
--- a/crates/bevy_pbr/src/cluster/mod.rs
|
||||
+++ b/crates/bevy_pbr/src/cluster/mod.rs
|
||||
@@ -239,8 +239,8 @@ impl Default for ClusterConfig {
|
||||
--- a/crates/bevy_light/src/cluster/mod.rs
|
||||
+++ b/crates/bevy_light/src/cluster/mod.rs
|
||||
@@ -185,8 +185,8 @@ impl Default for ClusterConfig {
|
||||
// 24 depth slices, square clusters with at most 4096 total clusters
|
||||
// use max light distance as clusters max `Z`-depth, first slice extends to 5.0
|
||||
Self::FixedZ {
|
||||
|
Loading…
Reference in New Issue
Block a user