-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Correctly handle visibility ranges in shadow maps. #24289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
74955d2
0f89ee2
eaa7dc5
34f7f24
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -840,6 +840,47 @@ impl Default for CameraOutputMode { | |
| } | ||
| } | ||
|
|
||
| /// The camera that Bevy uses to resolve visibility ranges when no specific | ||
| /// camera is applicable. | ||
| /// | ||
| /// For efficiency, Bevy currently renders point and spot light shadow maps only | ||
| /// once per frame, regardless of the number of cameras in use, rather than | ||
| /// rendering the shadow maps anew for each camera each frame. Most of the time, | ||
| /// this optimization doesn't change the result relative to a rendering that | ||
| /// rendered such shadow maps separately for each camera. However, there's one | ||
| /// exception: visibility ranges. Visibility ranges cause meshes to be visible | ||
| /// or invisible depending on the distance from the mesh to the camera. When | ||
| /// rendering a shadow map for a point or spot light, Bevy must therefore select | ||
| /// a camera as the reference camera for the purposes of visibility ranges. This | ||
| /// camera is known as the *primary camera*. | ||
| /// | ||
| /// Placing this component on a [`Camera`] makes that camera the primary one for | ||
| /// the purposes of shadow mapping of point and spot lights. | ||
| /// | ||
| /// The exact algorithm that Bevy uses to determine a primary camera is as | ||
| /// follows. Once a camera is chosen as the primary camera, all further steps | ||
| /// are skipped. | ||
| /// | ||
| /// 1. If a camera has this [`PrimaryCamera`] component, then it's the primary | ||
| /// camera. If there's more than one camera with the [`PrimaryCamera`] | ||
| /// component, one is chosen arbitrarily. | ||
| /// | ||
| /// 2. If a camera renders to a window (that is, the camera's [`RenderTarget`] | ||
| /// is [`RenderTarget::Window`]), then that camera is the primary one. If | ||
| /// there's more than one camera that renders to a window, then one is chosen | ||
| /// arbitrarily. | ||
| /// | ||
| /// 3. A primary camera is chosen arbitrarily from all cameras in the scene. | ||
| /// | ||
| /// This algorithm means that, in most cases, you don't need to add this | ||
| /// [`PrimaryCamera`] component explicitly to the scene; usually, Bevy chooses | ||
| /// the right camera automatically. You only need to use this component | ||
| /// explicitly if you have multiple cameras rendering to the window: e.g. a in a | ||
| /// split-screen game. | ||
| #[derive(Clone, Copy, Component, Default, Debug, Reflect)] | ||
| #[reflect(Clone, Component, Default)] | ||
| pub struct PrimaryCamera; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm nervous about the introduction of this. My understanding is that per-camera shadow maps is likely to always be too expensive. This design feels fundamentally wrong for split-screen games, even though it works for many others. Could we change the semantics here to allow for tagging multiple cameras, and then taking the union of shadows that should be seen by any of these cameras? We'd need to rename this component obviously. We can even bound the max number of cameras used for this comfortably: 4 or 8 is plenty.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That won't work for GPU driven because you would have a sequential loop over an array for every mesh in the shader. The right solution is
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In other words, per-camera shadow maps aren't necessarily too expensive. It really depends on the scene. There's a general feeling that they're too expensive by default, but we should support them at least on an opt-in basis. cart and Griffin disagree as to whether they should be enabled by default; I'm neutral on that question and simply think we should support both. |
||
|
|
||
| /// The "target" that a [`Camera`] will render to. For example, this could be a `Window` | ||
| /// swapchain or an [`Image`]. | ||
| #[derive(Component, Debug, Clone, Reflect, From)] | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like this fallback strategy: good defaults with manual control.