godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.14k stars 20.21k forks source link

Visibility Parent Omits Signals, doesn't work across Cameras #83289

Open thygrrr opened 11 months ago

thygrrr commented 11 months ago

Godot version

4.2.beta

System information

Windows 11

Issue description

Visibility Parents do not work across Cameras.

Their Dependents become visible only to the camera that trips the visibility range, and stick around permanently for any cameras that can't see the VisibilityParent

Expected behaviour:

They clearly should change visibility for all affected cameras and layers (it would be one of their primary uses, e.g. for layered rendering of foregrounds/backgrounds/environments with multiple cameras).

When any camera that could see the VisibilityParent trips its visibility change, any dependents, regardless of camera or viewport, their visibility should change accordingly.

Split-Screen games would use this with the same culling masks on both cameras, whereas games rendering large backdrops (space games, open world, etc.) would use it with differing culling masks between the various cameras.

Visibility Parents do not trigger Signal Node3D::visiblilty_changed.

This means it wouldn't even be possible to work around this bug, rendering the entire system rather useless as soon as more than one camera is involved.

Expected behaviour:

When a Node3D becomes visible based on its Visibility Parent, it should emit the signal Node3D::visiblilty_changed.

When a GeometryNode3D becomes visible or invisible based on its own Visibility Range parameters, it should emit the Node3D::visiblilty_changed signal. It should probably also emit another signal that is specific to GeometryNode3D, suggested name GeometryNode3D::dependents_visibility_changed, possiby with a bool parameter denoting the state.

Steps to reproduce

https://github.com/godotengine/godot/assets/8904620/00a29d0b-b160-4b93-beb6-67f75b2dde92

  1. Run attached project.
  2. Observe: Signal Listener never changes its text to "Wonders Happen", that means it never receives the connected visibility_changed signal from NEITHER the VisibilityParent NOR the working (cyan) VisibilityChind
  3. Observe: Background VisibilityParent properly triggers for Background Visibility Child.
  4. Observe: Foreground VisibilityChild (yellow) never changes visibility, should behave exactly the same as the cyan one.
  5. Observe: Cross-Layer VisibilityChild (red) changes visibility only on Background camera, behaves the same buggy way for the viewport camera.

Complication:

  1. Swap the cameras (parent the ForegroundCamera3D to the scene root, and the BackgroundCamera3D into the SubViewPort)
  2. Run project again.
  3. Observe: Behaviour is basically the same (apart for the render layering), ForegroundCamera3D still shows its two VisibilityChildren perpetually, only the BackgroundCamera works.

Minimal reproduction project

visibility-parent-bug-repro.zip

Calinou commented 11 months ago

cc @JFonS (in case he has an idea about how to resolve this :slightly_smiling_face:)

JFonS commented 11 months ago

I don't think I understand what your use case is.

Visibility ranges were developed mostly for HLOD purposes, so having per-camera dependency chains is not a bug, it's a design requirement. Otherwise, in a game with multiple cameras you could end up rendering high-detail objects far away in the distance or the lowest level meshes right in front of the camera, depending on your setup.

You want each camera to handle its dependency chain independently so the right LOD is chosen without other cameras affecting what gets rendered.

The behavior you expect should not be too hard to add, but I think this needs to be a proposal with a clearer explanation of the use cases instead of a bug report.

If the proposal moves forward I will be happy to help and give pointers to anyone interested in working on it.

thygrrr commented 11 months ago

If it's really for HLODs, the naming is a bit unfortunate.

I understand it as a feature that links visibility to geometry nodes.

Primarily to fade out things that should only render at a distance.

Secondarily to show other things conditionally.

Surely a use case for this is HLOD, but to me it's more like a map label fading out when the camera comes closer. Clouds appearing/disappearing. Or a cutaway Version of a house rendering when the camera is close enough, or a local view rendering when a open world camera is near a point of interest.

I'm working around it with Area3D and script logic, but I'm still using the fade out feature on Label3Ds where applicable.

Either way, I would expect the messages to be sent, or a specific note in the documentation which signals are being omitted, and possibly that this is always per-camera, never cross-camera.

If you want leave this ticket open for a bit, I can perhaps come up with a documentation edit for it.