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

Add Environment linear fog #54248

Closed
wants to merge 1 commit into from

Conversation

briansemrau
Copy link
Contributor

@briansemrau briansemrau commented Oct 26, 2021

Proposed solution to godotengine/godot-proposals#3429

This adds Environment properties for linear fog.

This nicely combines with exponential fog, allowing linear fog to completely obscure objects beyond a distance while exponential fog provides a more realistic effect in the interim.

The two are combined using the formula: `fog_amount = max(fog_exp, fog_linear)`

Blue: linear
Green: exponential
Dashed Red: combined

image

There is no need for any fog_mode enum property, as linear and exponential fog are combined and can be individually disabled (fog_density = 0 or fog_linear_end = 0).


Only exponential fog (current fog default):
image

Only linear fog:
(note: linear fog does not (yet?) effect the sky cubemap like exponential fog)
image

Combined linear and exponential:
image

Combined linear and exponential with aerial perspective:
image


Remaining tasks:

  • Exponential fog modifies the sky cubemap. Should linear fog do the same?
  • Maybe add a linear_fog_amount property to control the maximum linear fog density
  • Some kind of warning when fog_linear_start >= fog_linear_end

@briansemrau
Copy link
Contributor Author

@Calinou @clayjohn I'd appreciate your opinions on this method, if you'd like to take a look at the comparison screenshots.

This nicely combines with exponential fog, allowing linear fog to completely obscure objects beyond a distance while exponential fog provides a more realistic effect in the interim.
`fog_amount = max(fog_exp, fog_linear)`
@clayjohn
Copy link
Member

The results looks good and implementation looks good, but I am not sure it is needed.

To me, the purpose of #54222 is to allow fading in objects for open-world style games, I don't know how many games use fog to fade in objects at a distance. But I imagine it is not many as it will mostly only really work when using a flat sky color.

Ultimately, we also allow writing custom fog values in spatial shaders, so I don't really see why this needs to be builtin to the scene shader.

@briansemrau
Copy link
Contributor Author

To me, the purpose of #54222 is to allow fading in objects for open-world style games

Just to note, using per-instance distance fade from that PR with chunk-based loading will result in obvious chunk boundaries. A per-fragment approach is needed for that use case, whether it be fog, transparency, dithering or otherwise.

I don't know how many games use fog to fade in objects at a distance. But I imagine it is not many as it will mostly only really work when using a flat sky color.

A classic example where this is used is Minecraft. IMO, fog is a very easy and elegant solution to handling draw distance limits. It fades over all geometry evenly and at the same distance, just by configuring one or two properties. And with fog_aerial_perspective, it blends into the sky beautifully.

Ultimately, we also allow writing custom fog values in spatial shaders

As described in godotengine/godot-proposals#3429, implementing the same custom fog shader code for each material in a scene can quickly become tedious to create and maintain. It also requires converting every material into a shader material. I'll concede that that issue should be addressed directly, or perhaps there's a better way with the current system that I'm not aware of.
Regardless, I believe that built-in linear fog is a feature that some people will want to have as an option, even if not for obscuring draw distance limits.

@clayjohn
Copy link
Member

Don't forget, we also have fading built in to the StandardMaterial https://docs.godotengine.org/en/latest/classes/class_basematerial3d.html#class-basematerial3d-property-distance-fade-mode

Perhaps this could be a built in option in the StandardMaterial?

It is a tough thing to balance. On its own the PR is quite small. But it will have an impact on most 3D shaders in the engine. Remember, adding more variables into a shader increases VGPR pressure and reduces occupancy (and occupancy is a bit of a problem in the scene shader right now). So the tradeoff is between performance for all scene shaders and ease of use for people who want this feature (it would be a total pain to enable for every material/shader).

@briansemrau
Copy link
Contributor Author

Performance concerns are very real. Can't argue with that. I'll see if I can find some time to exploring those options you mentioned, as well as some other ideas I've got.

@briansemrau
Copy link
Contributor Author

I'll close this, but this should be marked salvageable should the feature be desired in the future.

With regards to custom fog, in its current state I think it is insufficient without godotengine/godot-proposals#944 or godotengine/godot-proposals#2595. Fog shouldn't be per-material, but per environment, even though it executes per material rather than as a post-process effect. Otherwise, I can't see many people using custom fog in a reasonably sized project, as maintainability becomes immensely challenging.

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

Successfully merging this pull request may close these issues.

3 participants