How can I render an arbitrary number of mutually isolated objects whilst retaining lighting from the root scene?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By CardboardComputers

The goal

To clarify, by ‘mutually isolated […] retaining lighting’, I mean a set of objects (or object hierarchies) such that:

  • Each object has a corresponding Viewport and Camera
  • The Camera renders only the corresponding object to its Viewport
  • The object appears to exist in the root scene’s environment (e.g. in terms of lighting and reflections)
  • None of the other objects in the set appear to exist in this Viewport

Degenerate case(s)

A solution for a single isolated object is provided here; it involves simply using VisualInstance layers and Camera cull masks to render the root scene and the target object separately. In this solution, it’s unnecessary to place the one target object in a separate World. However, this solution does not scale arbitrarily, as there are a limited number of render layers, and each mutually isolated object would need its own layer.

Generalisation problem

For example, suppose that there should be 22 ViewportContainers in the GUI, each of which should show one specific isolated object. The root scene should have both environment and dynamic lighting, along with some baked light probes for indirect lighting, and the player should be able to navigate this root scene in some form. In order to keep the lighting consistent across all of the objects as the immediate environment changes, all of the objects should simulate the same spatial transform within the root scene at any given time.

Since Godot includes only 20 render layers, but each object should be rendered separately from all of the other objects, the solution provided above is insufficient for this case.

From what I can tell, it would be necessary for each Viewport to use its own World. This would ensure that each object is rendered separately from the 21 other objects, thus being ‘mutually isolated’; however, this would also mean that each object is completely isolated from the root scene as well. The new problem would be to simulate the lighting from the root scene. It’s possible to copy the environment data to each Viewport, but this would not handle dynamic or indirect lighting.

Brute force

The most direct solution would probably be to instantiate a copy of the root scene for each Viewport and place the target object into the copied scene, using render layers to ensure that only the target object is actually rendered by the Viewport’s Camera. Since each Viewport would be using its own World, all of the objects could share one render layer.

Depending on the scene, it’s unlikely that this would be feasible, nor even produce a desirable effect. An approximated version could be to keep the dynamic lights and baked probes in a separate scene, and include an instance of this scene in the root scene as well as in each Viewport. This would still help ground the isolated objects in the root scene, although of course it wouldn’t include object shadows.

This was a very long hypothetical question

My guess is that the most efficient approach would be to use some kind of real-time lighting probe; since all of the isolated objects should simulate the same position in the root scene, you would only need to sample the root scene once per frame regardless of the number of Worlds, then apply the probed data to each of the isolated objects. So, without posing too many mutually isolated questions:

  • Is it possible to perform this kind of ‘apply lighting probed from a different scene’ feat in Godot?
  • If so, it actually a good idea?
  • If not, how should one go about simulating lighting for an arbitrary number of mutually isolated objects, assuming the degenerate case solution is not viable for the given number of objects?