godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

New scene instance type : Background #355

Open Flarkk opened 4 years ago

Flarkk commented 4 years ago

This proposal is based on issue https://github.com/godotengine/godot/issues/1006 from https://github.com/Ace-Dragon

Describe the project you are working on: A space exploration game within a very large universe

Describe the problem or limitation you are having in your project: I need to render both very far (and large) objects like planets and stars, and close objects (spaceship, terrain when exploring planets, ...). Today there are 2 limitations :

Describe how this feature / enhancement will help you overcome this problem or limitation: The proposal consists in a new type of scene instance, whose could be used as the background of another scene, either in « canvas » mode or in « panoramic » mode (with color, brightness, reflection, ... and all HDR ingredients). In combination with cameras settings within this background scene, it would allow to switch between per-frame or manual re-rendering

Show a mock up screenshots/video or a flow diagram explaining how your proposal will work: Simplistic proposal (but I'm sure much elegant solutions exist)

- Root of main scene
     - Nodes ...
     - ...
     - Camera_main -> Background set to render target of Camera_bg
- Root of background scene
     - Nodes ...
     - ...
     - Camera_bg -> Set to a new type of render "Panoramic background" that would take 360° pictures of the scene

This scheme could work with any number of "nested" background scenes

Describe implementation detail for your proposal (in code), if possible: Too vast topic to dive in detail here

If this enhancement will not be used often, can it be worked around with a few lines of script?: As far as I know it's impossible because there is no simple way to render "panoramic backgrounds" and use them as background of camera. The simplest workaround I can imagine would be to render the 6 faces of a cubemap, build a cubemap texture, convert it to an equirectangular projection (via a shader ?) and then use it as a background sky. This is not doable in a few lines of script, and the performance would probably be really poor ...

Is there a reason why this should be core and not an add-on in the asset library?: This should be core because of the large number of possible use cases, including :

Additionally this is a very common feature in commercial game engines (camera layers)

clayjohn commented 4 years ago

It doesn't take a lot of code to convert a scene to a background panorama. Here is a gist that does it https://gist.github.com/clayjohn/38f669030c9921ac176b6fa2a9ea86b2

Im not sure a new node is a good idea to achieve what you want. I think you should have two scenes, one with foreground elements and one with background elements. The background scene would only update when you need to and the resulting ViewportTexture would be used by the other scene as a background panorama.

Jummit commented 4 years ago

Because very far objects come in a very very high number (billion of stars ...) I can't render them each frame.

Just curious, has this ever been done before? Does it look good? (Wouldn't it be all white if every star is considered?) And even if it worked, does the player notice it?

Flarkk commented 4 years ago

One of the tricks is to « dim » the stars depending on their squared distance to the observer. And when too far packing them into clusters represented by a single mesh whose brightness is the sum of all packed stars. And also assuming your « packs » are cubes you can represent the entire space as a density function which can eventually be raymarched within a shader to render the very deep universe

MrMrBlackDragon commented 4 years ago

I need to render both very far (and large) objects like planets and stars, and close objects (spaceship, terrain when exploring planets, ...).

How about Threads? They might fit as well. You could realized it by letting them load your objects you need for your game. And due to the fact the Threads act parallel to your game, your game won't get interuppted.

GalaxyCr8r commented 4 years ago

This proposal would be moot if you could just choose the rendering order of objects which I don't understand why Godot doesn't allow. I want this feature for the exact same reason as @Flarkk.

Ideally we would be able to set some objects (Stars, Planets, Nebulae, etc.) to draw before nearby ships/stations, while other objects (Cockpit, Crew) draw after everything else.

I need to render both very far (and large) objects like planets and stars, and close objects (spaceship, terrain when exploring planets, ...).

How about Threads? They might fit as well. You could realized it by letting them load your objects you need for your game. And due to the fact the Threads act parallel to your game, your game won't get interuppted.

That's just an implementation detail to get better performance, not a factor in this proposal.

RicardRC commented 4 years ago

@clayjohn I love your solution, and thank you for making it public. But that solution seems to only partially work in 3.2 and the performance is abysmal. And I don't think we should need to be copying texture data around + using shaders to do something as "simple" as using a scene for sky. I know the implementation might not be trivial, but the use case is clear and the alternative workaround underperformant and not even real time. It does not even seem work in 4.0, but that might be another issue, or something I'm missing.

3.2 test: Skyboxer.zip

4.0 test: SkyTest.zip

I'm also supporting this proposal, it would be absolutely lovely to be able to put some slowly rotating planets in the background, that don't receive main scene object shadows, and having the main scene objects receiving reflections of the planets as if it was one of the current native panoramic skies.

GalaxyCr8r commented 4 years ago

@RicardRC - the links are reversed - I can open the 4.0 test in 3.2 but not the 4.0 test.

RicardRC commented 4 years ago

@RicardRC - the links are reversed - I can open the 4.0 test in 3.2 but not the 4.0 test.

True! Fixed.

Calinou commented 2 years ago

I'm also supporting this proposal, it would be absolutely lovely to be able to put some slowly rotating planets in the background, that don't receive main scene object shadows, and having the main scene objects receiving reflections of the planets as if it was one of the current native panoramic skies.

Sky shaders make all this possible in 4.0 🙂

To prevent an object from receiving shadows in 3.x, enable Do Not Receive Shadows on its SpatialMaterial.

goatchurchprime commented 1 year ago

This proposal has applications to VR where we require a high frame rate to run on low power mobile hardware.

The Blink-Teleportation method of VR locomotion could be a natural place to deploy this feature, where the player points to the spot on the ground they want to jump to and the scene briefly fades to black to give a sense of transition. This would be a good time to render the six cameras that make up the sky box. The distance of the cut-off is defined by the amount of parallax that could be visible to the player in the VR guardian boundary (usually less than 5m), so should be no less than 100m.

Not perfectly related, but similar to this is the deprecated MonoFarFieldRendering in UE.