Skip to content
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

Mechanism for inheritable render layers #12461

Open
viridia opened this issue Mar 13, 2024 · 3 comments
Open

Mechanism for inheritable render layers #12461

viridia opened this issue Mar 13, 2024 · 3 comments
Labels
A-Rendering Drawing game state to the screen A-Scenes Serialized ECS data stored on the disk C-Feature A new feature, making something new possible D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Ready-For-Implementation This issue is ready for an implementation PR. Go for it!

Comments

@viridia
Copy link
Contributor

viridia commented Mar 13, 2024

What problem does this solve or what need does it fill?

Currently render layers only affect the entity that they are attached to, not their descendants. This is problematic for a number of reasons: for example, if I load a GLTF scene and spawn a SceneBundle, I can add a render layer to the bundle, but it has no effect on the models contained within the scene. While I can manually iterate through the scene bundle and add RenderLayers components, this doesn't help if I have multiple instances of the scene which need to appear in different layers.

What solution would you like?

Because inheritance requires additional calculation, I propose adding a new optional component (or perhaps a new property on RenderLayers) which would cause the layer settings to apply to all descendants, except for descendants which explicitly had their own layer settings. This would operation much like the existing visibility calculations, and probably could be performed in the same tree traversal.

What alternative(s) have you considered?

At the moment I'm manually iterating over descendants and adding render layers, but this adds a lot of extra complexity.

@viridia viridia added C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled labels Mar 13, 2024
@SolarLiner SolarLiner added A-Rendering Drawing game state to the screen A-Scenes Serialized ECS data stored on the disk and removed S-Needs-Triage This issue needs to be labelled labels Mar 13, 2024
@viridia
Copy link
Contributor Author

viridia commented Mar 16, 2024

Hopefully this will be solved by #12502 .

@mrchantey
Copy link
Contributor

mrchantey commented Oct 27, 2024

In the meantime here's an observer that applies RenderLayers to children on SceneInstanceReady:

use bevy::prelude::*;
use bevy::render::view::RenderLayers;
use bevy::scene::SceneInstanceReady;

/// Currently [`RenderLayers`] are not applied to children of a scene.
/// This [`SceneInstanceReady`] observer applies the [`RenderLayers`]
/// of a [`SceneRoot`] to all children with a [`Transform`] and without a [`RenderLayers`].
/// 
/// See [#12461](https://github.com/bevyengine/bevy/issues/12461) for current status.
pub fn apply_render_layers_to_children(
  trigger: Trigger<SceneInstanceReady>,
  mut commands: Commands,
  children: Query<&Children>,
  transforms: Query<&Transform, Without<RenderLayers>>,
  query: Query<(Entity, &RenderLayers)>,
) {
  let Ok((parent, render_layers)) = query.get(trigger.entity()) else {
    return;
  };
  children.iter_descendants(parent).for_each(|entity| {
    if transforms.contains(entity) {
      commands.entity(entity).insert(render_layers.clone());
    }
  });
}

Usage:

// apply globally
app.add_observer(apply_render_layers_to_children);

// or per scene
let scene = asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb"));
commands.spawn(SceneRoot(scene))
  .observe(apply_render_layers_to_children);

@BenjaminBrienen BenjaminBrienen added S-Ready-For-Implementation This issue is ready for an implementation PR. Go for it! D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes labels Oct 27, 2024
@coreh
Copy link
Contributor

coreh commented Dec 24, 2024

@mrchantey Thanks for that snippet, it was really helpful. I didn't know about SceneInstanceReady, the implementation I was going for was much uglier.

One small suggestion when using the per-scene .observe() is to despawn the observer at the end of apply_render_layers_to_children, since it won't be used again:

commands.entity(trigger.observer()).despawn();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen A-Scenes Serialized ECS data stored on the disk C-Feature A new feature, making something new possible D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Ready-For-Implementation This issue is ready for an implementation PR. Go for it!
Projects
None yet
Development

No branches or pull requests

5 participants