How to change shadow opacity in gdshader

Godot Version

4.4

Question

Hello everyone! For the last couple days I have been trying to create moving cloud shadows in my 3d game. Right now I have a plain mesh with a scrolling and evolving 2d noise texture hovering above my world that casts shadows based on a threshold value for alpha_scissor_cutoff. However I would like for these cloud shadows specifically to have a different opacity with a select number of bands based on the noise texture (see the picture below for the style im trying to recreate). Im not sure if i should do something in the light or fragment function and how to change/fake the shadow opacity. Any help is greatly appreciated! :)

CODE:

shader_type spatial;

uniform sampler2D noise : filter_linear;
uniform sampler2D bump : hint_normal;
uniform float threshold : hint_range(0.0, 1.0) = 0.5;
uniform float speed : hint_range(0.0, 16.0) = 1.0;
uniform vec2 uv_scale = vec2(1.0, 1.0);
uniform float evolve_speed : hint_range(0.0, 2.0) = 0.1;

varying vec2 uv_normal;

void vertex()
{
	float fps = 30.0;
	float quantized_time = floor(TIME * fps) / fps;

	uv_normal = UV + quantized_time;
	UV = (UV * uv_scale) + quantized_time * speed;
}

void fragment(){
	vec3 distortion = texture(bump, uv_normal).rgb;

	float base_noise = texture(noise, UV + distortion.xy).r;
	
	vec2 evolved_uv = UV + distortion.xy + vec2(0.0, TIME * evolve_speed);
	float scrolling_noise = texture(noise, evolved_uv).r;

	float final_noise = mix(base_noise, scrolling_noise, 0.2);

	ALPHA = final_noise;
	ALPHA_SCISSOR_THRESHOLD = threshold;
}

Sounds like you do not want to use ALPHA_SCISSOR_THRESHOLD if you intend to change opacity, maybe a step function?

Yeah you’re right! I already have a normal toon shader for objects in the world that works that way so the stepping is no problem. Im just not sure in the above shader what i should access to change the opacity.

You can set your noise texture to use constant interpolation

Thanks a lot :star_struck:! The texture itself now looks way better! But how do I get the texture to work like a shadow now? You can see my setup in the image: if I don’t use ALPHA_SCISSOR_THRESHOLD then there are no shadows at all right now.

I think Godot only supports 1-bit shadow maps for dynamic lights/shadows, you may need to take another approach than physically lighting the texture. Maybe you can use a shader on your map or the mesh quad to overlay the clouds as a fake shadow? A spotlight could project a multi-color noise texture, but not a shader so you’d have to animate the noise or spotlight seperately.

There is some talk on a open issue about semi-transparent objects casting shadows, but then alpha-hash would get you a similar but worse effect.