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

Implement a bounding-box/volume-based approach for local environments and post-processing #4466

Open
PrecisionRender opened this issue Apr 29, 2022 · 21 comments

Comments

@PrecisionRender
Copy link

PrecisionRender commented Apr 29, 2022

Describe the project you are working on

A 3D project that has multiple different themed areas.

Describe the problem or limitation you are having in your project

The WorldEnvironment node and resource are global, to the entire scene. There is no way to set up a smaller area (e.g. inside a volcano) to have a different post processing setup to the rest of the scene.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Most game engines, like Unity and UE5, use a volume-based approach, where one can specify post processing settings inside of an AABB, that can modify a predefined area's post processing effects. Example:

World has XY as global ambient light

Smaller volume has WZ as local ambient light inside of predefined area

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Instead of a WorldEnvirinment node, there would be an EnvironmentVolume node, where one could specify the post processing effects that are active inside of the area. Or, one can turn off an option such as "Is Bounded" so that the EnvironmentVolume node acts as a WorldEnvironment node. Then one can put more EnvironmentVolume nodes into the Scene where one needs different post processing.

UE_1.mp4

Here is an example of a global post-process volume (left) and a local post-process volume (right).

If this enhancement will not be used often, can it be worked around with a few lines of script?

No, this system requires quite deep knowledge on how environments are rendered, and the code required to blend between them is quite complex.
Plus, having such a node built-in allows the ability for one to move the viewport camera into an EnvironmentVolume area and examine its effects in the editor, whereas if such a tool was scripted, post processing areas could only be examined at runtime, by changing WorldEnvironments dynamically through code.

And something that can't be easily achieved through GDScript or even GDExtension is having a proper fade between areas, so as not to have a sharp "pop" between different visual effects.

Is there a reason why this should be core and not an add-on in the asset library?

See above.

@mrjustaguy
Copy link

This would be very useful for games that need transitions between land and water

@Calinou
Copy link
Member

Calinou commented Apr 29, 2022

Unfortunately, I feel this can lead to shaders being extremely complex to support this, reducing performance significantly. It's not like the renderer is too fast as it currently is 🙂

And something that can't be easily achieved through GDScript or even GDExtension is having a proper fade between areas, so as not to have a sharp "pop" between different visual effects.

Most Environment properties can be smoothly tweened over time with no performance impact. This will not work if you want different areas viewed at the same time to use different properties, but for a player travelling through a game world, it can be a good enough solution.

If you want to perform color grading based on where the player is currently located, smooth transitions could be better supported by allowing the blending of two color correction curves together. Local color grading of that kind is common in AAA games, and it's not too expensive to support. This could be worth discussing in a separate proposal, as I don't see a way to work this around currently (especially with 3D LUTs supported in Godot 4.0).

Smaller volume has WZ as local ambient light inside of predefined area

This can be achieved with a ReflectionProbe node, which can smoothly override ambient light within a defined box (that can be rotated). You can either use the environment color, or use a custom ambient color of your choice. This is available in both Godot 3.x and Godot 4.0, but Godot 4.0 offers more options in this aspect.

FogVolume nodes are also available in Godot 4.0 for local fog, and they can use custom fog shaders as well.

@PrecisionRender
Copy link
Author

I feel this can lead to shaders being extremely complex to support this, reducing performance significantly. It's not like the renderer is too fast as it currently is 🙂

Most Environment properties can be smoothly tweened over time with no performance impact.

Then can't we just do something with tweens, like you suggested? It doesn't have to be a shader.

@PrecisionRender
Copy link
Author

PrecisionRender commented Apr 29, 2022

FogVolume nodes are also available in Godot 4.0 for local fog, and they can use custom fog shaders as well.

Yes, the FogVolume nodes are excellent. I was thinking of something similar for the entire WorldEnvironment. Not necissarily things like SDFGI, SSAO, SSIL, or SSR. Just things that have a greater aesthetic impact, like Skies, Ambient Light, Color Grading, etc.

@Calinou
Copy link
Member

Calinou commented Apr 29, 2022

Then can't we just do something with tweens, like you suggested? It doesn't have to be a shader.

By "shader", I was referring to the GLSL shaders internally used in Godot to render various materials. It's important to keep those simple to improve performance and reduce shader compilation times.

I was thinking of something similar for the entire WorldEnvironment. Not necissarily things like SDFGI, SSAO, SSIL, or SSR. Just things that have a greater aesthetic impact, like Skies, Ambient Light, Color Grading, etc.

How would local skies work? I feel it doesn't make sense, at least from a background perspective. You can already use ReflectionProbes if you need custom reflections within an area. (If you want a reflection that actually doesn't reflect the surroundings, use a sphere with a texture around the ReflectionProbe and hide this sphere after the ReflectionProbe is done rendering.)

@PrecisionRender
Copy link
Author

How would local skies work? I feel it doesn't make sense, at least from a background perspective.

I was just using it as an example. Skies don't necessarily need to change.

By "shader", I was referring to the GLSL shaders internally used in Godot to render various materials. It's important to keep those simple to improve performance and reduce shader compilation times.

That is important; something that Godot does well compared to other engines is shader compilation. I was suggesting doing the calculations in regular C++, then feeding that into a shader, like how the WorldEnvironment does.

TL;DR: The EnvironmentVolume node decides what effects and parameters to use, then those are fed into the World3D. As far as the World3D is concerned, it's just one Environment resource, keeping all the shaders the same as they are now.

@clayjohn
Copy link
Member

I imagine we could have something like a "LocalEnvironment" Node that overrides the current WorldEnvironment. We would have to limit it to only interpolate easily interpolatable properties (other properties like sky could just snap to the new resource when in the volume). I'm sure you could manage everything in the SceneTree well enough that you could avoid doubling any calculations in the rendering code.

@PrecisionRender
Copy link
Author

I imagine we could have something like a "LocalEnvironment" Node that overrides the current WorldEnvironment. We would have to limit it to only interpolate easily interpolatable properties (other properties like sky could just snap to the new resource when in the volume). I'm sure you could manage everything in the SceneTree well enough that you could avoid doubling any calculations in the rendering code.

This is also a good idea.

@Calinou
Copy link
Member

Calinou commented Apr 29, 2022

Looking at the video1, I finally understood what you mean. I was initially thinking that you'd expect different pixels to use different Environment properties, rather than affecting the entire view at once. This seems like a reasonable approach to me.

Footnotes

  1. The video doesn't preview in Firefox (I get "No video with supported format and MIME type found."). I managed to view it by right-clicking it, copying the video link and opening the copied video link in a new tab.

@PrecisionRender
Copy link
Author

Ah, yes, I guess I was relying too much on the video to explain it for me. 😅 Sorry. Yes, it should effect the entire view based on the camera position.

@SIsilicon
Copy link

What if you give the already existing Area nodes an environment property?

@DarkKilauea
Copy link

DarkKilauea commented Apr 30, 2022

I wrote an addon that addresses many of your requirements. It acts much like the UE4 post processing volume, though it doesn't support blending between volumes yet.

Give it a try: https://github.com/DarkKilauea/godot-environment-volume

If there is interest in integrating it directly into Godot, I'd be willing to port it.

@PrecisionRender
Copy link
Author

PrecisionRender commented Apr 30, 2022

@DarkKilauea Your addon looks great! It appears like it adds pretty much everything an EnvironmentVolume node would need, minus blending.

If you can get blending between volumes working, this addon would be a great thing to add to the core.

Edit: I've tried your addon. It was a bit of work to get running, but it's functionality would be great to add to the core.

@Calinou
Copy link
Member

Calinou commented Apr 30, 2022

I like the idea of adding this functionality to Area, as it's already where audio bus overrides can be performed. This would also allow using arbitrary shapes rather than being limited to boxes (and perhaps ellipses).

Figuring out the blending situation with Areas is likely more difficult though. You could make it so the override is active whenever the camera is within the Area, while fading it out progressively as the camera gets closer to its edges. However, with arbitrary collision shapes, there may not be an easy solution to this. Time-based blending could be used as an alternative (e.g. crossfade over a time period defined in the Area node). It's much simpler to implement, but it doesn't work as well if the player can move slowly and backtrack around the Area.

@PrecisionRender
Copy link
Author

Time-based blending could be used as an alternative (e.g. crossfade over a time period defined in the Area node). It's much simpler to implement, but it doesn't work as well if the player can move slowly and backtrack around the Area.

@Calinou I think that time-based blending would work, as the game developer can adjust the fade-time based on the speed of the player if needed. I guess it's a question of whether custom shapes are worth more than distance-based blending.

@Zireael07
Copy link

+1 to having something available in the core for areas (I have a game using water areas, currently I fake things by having a roughly box shaped mesh and some shaders)

@PrecisionRender
Copy link
Author

I'm good with Areas, too.

@mrjustaguy
Copy link

+1 for this to be in Areas.

How to solve blending - Make a Margin around the Collision shapes, have a way to determine how far you are from exiting/entering. all Primitive based Collision Shapes would work, and Convex would also be easy to calculate this, and Trimeshes aren't volumes anyway (at least not to the Engine)

@Calinou Calinou changed the title Implement a bounding-box/volume-based approach for post processing Implement a bounding-box/volume-based approach for local post-processing Jun 17, 2022
@Calinou Calinou changed the title Implement a bounding-box/volume-based approach for local post-processing Implement a bounding-box/volume-based approach for local environments and post-processing Jul 31, 2022
@PrecisionRender
Copy link
Author

@DarkKilauea I took another look at your plug-in. It looks great! Would you mind if I used it as a base to try to bring it into the engine?

Of course, if you'd rather do it yourself, then I won't.

@osayami
Copy link

osayami commented Feb 18, 2025

When a similar request was made in https://github.com/godotengine/godot/issues/21048 Reduz said

This is one of the reasons why I wanted to split WorldEnvironment into effects and post processing eventually, so you can animate or switch between post processes and leave other parameters such as SSR/SSAO/etc alone.

here https://github.com/godotengine/godot/issues/21048#issuecomment-425639647 . I would imagine this is not something that would be done in 4.x right?

@Calinou
Copy link
Member

Calinou commented Feb 18, 2025

I would imagine this is not something that would be done in 4.x right?

Not currently. This is being tracked in #2196, although I don't know if splitting built-in effects to be usable independently is still planned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants