Closed unfa closed 1 year ago
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.
@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:
Versus:
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 https://github.com/godotengine/godot/issues/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 https://github.com/godotengine/godot/pull/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.
@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.
For additive materials it looks like you can add:
ALBEDO -= FOG.rgb;
at the end of the shader to remove the fog.
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
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.
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?
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.
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.
Having the same problem using a StandardMaterial3D, unshaded and set to additive.
@bertodelrio256 @joshua-maros how did you implement your solution?
Having the same problem using a StandardMaterial3D, unshaded and set to additive.
@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
@bertodelrio256 Wonderful, thank you very much!
@clayjohn Should we add a toggle in StandardMaterial3D that performs ALBEDO -= FOG.rgb
? Perhaps this could be exposed as a Fog Affect enum property:
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
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)?
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.
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)
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.
To add a new render mode:
define the mode here: https://github.com/godotengine/godot/blob/ff5c884153d1c15bde3ee87aa295e52bec3a6340/servers/rendering/shader_types.cpp#L229-L230
Add a render mode define here: https://github.com/godotengine/godot/blob/ff5c884153d1c15bde3ee87aa295e52bec3a6340/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp#L709 here: https://github.com/godotengine/godot/blob/ff5c884153d1c15bde3ee87aa295e52bec3a6340/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp#L612 and here: https://github.com/godotengine/godot/blob/ff5c884153d1c15bde3ee87aa295e52bec3a6340/drivers/gles3/storage/material_storage.cpp#L1360
And add the corresponding defines to the shaders
I'd also recommend adding a Disable Fog property to BaseMaterial3D, so you can toggle this on built-in materials.
Is someone working on this? Otherwise I would give it a shot as it is affecting the visuals of my game quite heavily.
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.
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
Steps to reproduce
Minimal reproduction project
Fog Volume Additive.zip