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

Fog volume breaks additive unshaded materials #56374

Closed
Tracked by #69579
unfa opened this issue Dec 31, 2021 · 22 comments · Fixed by #81286
Closed
Tracked by #69579

Fog volume breaks additive unshaded materials #56374

unfa opened this issue Dec 31, 2021 · 22 comments · Fixed by #81286

Comments

@unfa
Copy link

unfa commented Dec 31, 2021

Godot version

4.0 dev

System information

Arch Linux, KDE Plasma, Radeon RX580, amdgpu driver

Issue description

The plane is textured with a radial gradient and should produce a smooth transition between nothing and white. The fog volume however breaks that and makes edges of the mesh clearly visible, which is not what the mesh is supposed to look like.

1: this is the expected look
2: this is the unexpected look when fog volume interacts with the additive unshaded mesh

image

Steps to reproduce

  1. Create an unshaded additive material with a gradient from black to color.
  2. Add a fog volume and enable fog volume in Environment settings
  3. Make the fog volume overlap the mesh
  4. See as the mesh looses it's indented look

Minimal reproduction project

Fog Volume Additive.zip

@clayjohn
Copy link
Member

I don't think this is a bug. The mesh in your example is opaque and set to additive. Additive blending specifies that the resulting color from the shader should be added to whatever is behind it in the render target. In this case, the fog is calculated as part of the mesh's color (making it so the object is no longer plain black) and then added to the fog that is behind it.

The solution is to use a transparent mesh that fades to (0,0,0,0) instead of an opaque mesh that fades to black (0,0,0,1).

To me the big question that arises is, should unshaded meshes receive fog? The issue here arises because the fog color is calculated even for the black parts of the additive mesh.

@unfa
Copy link
Author

unfa commented Jan 15, 2022

@clayjohn Thanks, I now understand why this happens. And I think I have an idea on how to avoid it.

BTW, non-volumetric fog also does this:
image

Versus:
image

@Calinou
Copy link
Member

Calinou commented Nov 28, 2022

There's a disable_fog render mode you can use in custom shaders, but it's not exposed as a property in BaseMaterial3D. If it's exposed, we could make fog affect unshaded materials, but the documentation would advise you to disable fog on the material in most situations.

Edit: disable_fog is exposed in BaseMaterial3D since 4.2.

Quotring from #69268:

Fog does not affect unshaded materials in Godot 3, so unless I'm missing something this should not be happening in Godot 4 either

Fog on unshaded materials is a controversial thing – see #29141. There is no universally right approach here, as many people do need fog to apply on unshaded materials (e.g. in games with a retro art style that don't rely on real-time lighting at all). You may also be using unshaded as a cheap approximation of emissive materials, and you want fog to apply on those materials as well.

@EzraT
Copy link

EzraT commented Nov 28, 2022

@Calinou Godot4 beta 6 does not seem to recognize a "disable_fog" render mode currently, and if it does exist it would be very helpful if it could indeed also be exposed to BaseMaterial3D, so the old Godot 3 behavior can still be used.

@someguynamedjosh
Copy link

For additive materials it looks like you can add:

ALBEDO -= FOG.rgb;

at the end of the shader to remove the fog.

@unfa
Copy link
Author

unfa commented Jan 30, 2023

Hmm. Right now have all my additive materials switched to emissive shaded. But.. I get a dark overlay from the parts that should be transparent, even without any fog. Can't win :D

@clayjohn clayjohn modified the milestones: 4.0, 4.x Feb 23, 2023
@RPicster
Copy link
Contributor

RPicster commented Mar 6, 2023

Hm, from my point of view, this is a bigger problem then it get's credit.
It's not possible making a good looking particle effect like e.g. Fire while using fog.

It will change the way the material appears and makes the edges visible.
image

From my point of view, disable_fog should be the default and could be exposed as a flag in the StandardMaterial3D.
The situations where you want this behaviour are more rare than the situations where it is the expected behaviour (especially with blend_add.

Can we gather some examples of Sitations where one or the other behaviour would be preferable?

@unfa
Copy link
Author

unfa commented Mar 7, 2023

I had to get rid of all volumetric fog from Liblast, because no matter what I do I can't get it to not screw up all the unshaded billboards.

@bertodelrio256
Copy link

For additive materials it looks like you can add:

ALBEDO -= FOG.rgb;

at the end of the shader to remove the fog.

This worked for me. additive particles look correct in fog now.

@LauraWebdev
Copy link

Having the same problem using a StandardMaterial3D, unshaded and set to additive.

image

@bertodelrio256 @joshua-maros how did you implement your solution?

@bertodelrio256
Copy link

Having the same problem using a StandardMaterial3D, unshaded and set to additive.

image

@bertodelrio256 @joshua-maros how did you implement your solution?

this will not work on a StandardMaterial3D as the fog logic is hard coded. You can right click on your material instance on the mesh and click "convert to shadermaterial" then open the shader code and add ALBEDO -= FOG.rgb at the end of the fragment() function

@LauraWebdev
Copy link

@bertodelrio256 Wonderful, thank you very much!
image

@Calinou
Copy link
Member

Calinou commented Jun 30, 2023

@clayjohn Should we add a toggle in StandardMaterial3D that performs ALBEDO -= FOG.rgb? Perhaps this could be exposed as a Fog Affect enum property:

  • Automatic (disable for unshaded materials, enable otherwise)
  • Enabled
  • Disabled

@clayjohn
Copy link
Member

disable_fog

I really think we should just add a disable_fog render mode like we have in sky shaders and then expose a toggle in StandardMaterial3D. ALBEDO -= FOG.rgb is a nice workaround, but its not something we should integrate into the engine code as it is a total hack.

I'm not sure why fog is affecting unshaded materials in the first place. In 3.x unshaded materials were not affected by fog. In hindsight, we probably should have just made 4.0 match 3.x, but here we are. I don't want to break compatibility at this point, so the best solution is to allow users to disable fog

@LauraWebdev
Copy link

I don't want to break compatibility at this point

Is that a realistic situation? At this state, without this hack, unshaded additive materials are just broken, how would a fix break compatibility (genuinely trying to understand here)?

@Calinou
Copy link
Member

Calinou commented Jun 30, 2023

At this state, without this hack, unshaded additive materials are just broken, how would a fix break compatibility (genuinely trying to understand here)?

Unshaded materials don't necessarily use the additive blend mode, and additive blend mode materials aren't necessarily unshaded. Some people may now be relying on the current behavior in 4.x, so changing it breaks expectations.

In my experience, you don't want unshaded materials to always ignore fog (when using unshaded opaque materials to improve rendering performance), and you sometimes want shaded materials to ignore fog (e.g. to allow players to be better seen in low-density fog). This is why exposing an enum that would adjust a disable_fog spatial shader render mode makes the most sense to me.

@LauraWebdev
Copy link

At this state, without this hack, unshaded additive materials are just broken, how would a fix break compatibility (genuinely trying to understand here)?

Unshaded materials don't necessarily use the additive blend mode, and additive blend mode materials aren't necessarily unshaded. Some people may now be relying on the current behavior in 4.x, so changing it breaks expectations.

In my experience, you don't want unshaded materials to always ignore fog (when using unshaded opaque materials to improve rendering performance), and you sometimes want shaded materials to ignore fog (e.g. to allow players to be better seen in low-density fog). This is why exposing an enum that would adjust a disable_fog spatial shader render mode makes the most sense to me.

Makes sense. Would you say implementing a fix only for this use case (where we know it's just broken) would be out of the question? I can't think of a situation where you would create an unshaded additive Material and actually just want it to be white. (Unless of course the project structure doesn't allow for such pinpointed fixes)

@QbieShay
Copy link
Contributor

Adding to this, it seems like the consensus is that it should be a flag, because it should be on for some cases, off for others.

@clayjohn
Copy link
Member

To add a new render mode:

define the mode here:

shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("debug_shadow_splits") });
}

Add a render mode define here:

actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n";

here:
actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n";

and here:
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";

And add the corresponding defines to the shaders

@Calinou
Copy link
Member

Calinou commented Aug 18, 2023

I'd also recommend adding a Disable Fog property to BaseMaterial3D, so you can toggle this on built-in materials.

@lemilonkh
Copy link
Contributor

Is someone working on this? Otherwise I would give it a shot as it is affecting the visuals of my game quite heavily.

@jitspoe
Copy link
Contributor

jitspoe commented May 30, 2024

For additive blending, I really think we should be using a fog color of 0, regardless of what the fog color is set to, that way stuff that has additive blending (like fire FX) will fade out in the distance with everything else covered by fog. I can't think of a scenario where you'd want the fog additively blending onto the scene -- that should probably not be the default behavior and there could be an option to switch to that behavior if so desired, but I think it should "just work" (and fade) by default.

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

Successfully merging a pull request may close this issue.