Here's how Godot does it with the distance fade in SpatialMaterial (trimmed to just essentials):
shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx;
uniform vec4 albedo : hint_color;
uniform float distance_fade_min;
uniform float distance_fade_max;
void fragment() {
ALBEDO = albedo.rgb;
ALPHA = albedo.a;
// Original - exactly how it was converted
// ALPHA *= clamp(smoothstep(distance_fade_max,distance_fade_min,-VERTEX.z),0.0,1.0);
// Flipped min and max so it fades as you get farther away, rather than closer
ALPHA *= clamp(smoothstep(distance_fade_max,distance_fade_min,-VERTEX.z),0.0,1.0);
}
It looks like the alpha is being manipulated to cause the fading.
Edit: Turns out it has the same shadow issue. The Turns out the only distance fade that Godot supports out of the box that supports shadows as well is ObjectDither
...
Edit 2: In the ObjectDither
code, it uses discard. If you swap distance_fade_min
and distance_fade_max
around though, it looses its shadow as well. I'm thinking this may be a bug or something, to be honest, as the behavior doesn't make too much sense.
Edit 3: I don't know. I've been messing around with the shaders and I'm not sure why it casts a shadow if fading in using ObjectDither
, but not fading out. I guess as a possible, though not optimal workaround would be to have two objects, one that just casts shadows and the other that is the visuals only that does not cast shadows.