Godot Version
4.2
Question
I’m not talking about shadows generated by lights, but simple shadows drawn as a mask on background objects, like this:
I found a simple shader that does this. The problem is that it draws shadows both over objects behind and over the background. An undesirable behavior if the background is a blue sky or the starry space. I think the problem is not in the shader, but that there is no way not to apply it to lower layers.
Here’s an example of what I’m talking about:
Above is the desired behavior, below is the undesired behavior.
The solution I found is a bit trichy. I have to put the scene with all sprites in a SubViewport with transparent bg flag set, then apply to the foreground objects a modified version of the shader that takes into account the background color of the viewport. Then the scene is draw over the background using a TextureRect whose texture is get from the SubViewport.
Here is my version of the shader:
shader_type canvas_item;
uniform vec2 offset = vec2(8.0, 8.0);
uniform vec4 modulate : source_color;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, repeat_disable, filter_nearest;
uniform vec4 background_color: source_color;
void fragment() {
vec4 texture_col = texture(TEXTURE, UV);
vec4 screen_col = texture(SCREEN_TEXTURE, SCREEN_UV);
vec4 shadow = vec4(modulate.rgb, texture(TEXTURE, UV - offset * TEXTURE_PIXEL_SIZE).a * modulate.a);
vec4 shadow_over_bg = mix(screen_col, shadow, screen_col.a);
vec4 bg_color = texture(SCREEN_TEXTURE, SCREEN_UV);
if (bg_color.rgba == background_color) {
COLOR = texture_col;
} else {
COLOR = mix(shadow_over_bg, texture_col, texture_col.a);
}
}
It works. But I don’t like it.
I’m not very expert about Godot and game engines in general, so I imagine there might be a better solution. Anyone have a suggestion?