• Godot HelpShaders
  • Disappearing shadows when using distance fade. What am I doing wrong?

I am using distance fade to smoothly change LODs.

In fact, I tried scaling objects, which also gives the effect of disappearing shadows.


if( INSTANCE_CUSTOM.r == 1.0 ) //LOD ID
	{
	scale = clamp(smoothstep( 60.0, 40.0, fade_distance ), 0.0, 1.0);
	}
	
	VERTEX = (VERTEX  -  world_obj_pos) * scale + world_obj_pos;
//___________________________________________
OR
//___________________________________________

	int x = int(FRAGCOORD.x) % 4;
	int y = int(FRAGCOORD.y) % 4;
	int index = x + y * 4;

	const float limits [16] = {0.0625, 0.5625, 0.1875, 0.6875, 0.8125, 0.3125, 0.9375, 0.4375, 0.25, 0.75, 0.125, 0.625, 1.0, 0.5, 0.875, 0.375};
	float limit = limits[index];

	float fade_distance = abs((INV_CAMERA_MATRIX * WORLD_MATRIX[3]).z);
	float fade = clamp( smoothstep( 49.0, 50.0, fade_distance), 0.0, 1.0);

What am I doing wrong? Please, help))

Welcome to the forums @"Wayfarlands Engine"!

When do the shadows disappear? When the object is far away or close nearby? If the issue occurs when the objects are far away, are you sure that the shadow distance for the light you are using reaches far enough?

@TwistedTwigleg said: Welcome to the forums @"Wayfarlands Engine"! Thanks )

@TwistedTwigleg said: When do the shadows disappear? When the object is far away or close nearby? If the issue occurs when the objects are far away, are you sure that the shadow distance for the light you are using reaches far enough?

So, no. Shadow disappearing occurs when a shader is written in a specific way, regardless of the distance to the object. Here video demonstration:

Ah, I think I see the issue and know a few things you can try that may help. Instead of using discard, you could maybe try COLOR.a = 0. Another thing to try is using return rather than discard, and see if that helps.

My guess is that the discard function call is the issue, as for some reason it is making the shadow mapping code skip all of the polygons of the grass rather than just those that have their pixels discarded. I think altering the alpha instead should fix the issue, though I'm not sure if performance would improve or not though. I think Godot has a SpatialMaterial setting for fading over distance, so it should be possible to do some form of fading through a custom shader.

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.

@TwistedTwigleg said: 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.

Yes, I went through the same path))

I wanted to use this shader to change LODs, so using two objects for the shadows and for rendering, of course, doesn't make any sense.

Do you think this is a bug and it makes sense to create an issue on githab?

@"Wayfarlands Engine" said:

@TwistedTwigleg said: 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.

Yes, I went through the same path))

I wanted to use this shader to change LODs, so using two objects for the shadows and for rendering, of course, doesn't make any sense.

Yeah, and having one render shadows and the other render visuals wouldn't really save any performance, at least I would not expect it to.

Do you think this is a bug and it makes sense to create an issue on githab?

I think it would be worth reporting, as even the built-in solutions do not behave correctly when fading out with shadows. At least for ObjectDither, since it only casts shadows when fading as the camera gets close. That said, my experience with shaders and Godot's rendering engine is limited, so I'm not 100% confident it isn't just a known technical bug or something strange with OpenGL. Regardless, I would suggest opening an issue on it if you want, as I do think it is at least something that should be noted if not a bug.

2 years later