// Cloud shadow sampling — include in any spatial shader's light() function
// to receive cloud shadows projected from the cloud plane.
//
// Usage in your shader:
// 1. Add these uniforms:
// uniform float cloud_shadow_altitude;
// uniform float cloud_shadow_scale;
// uniform vec2 cloud_shadow_wind_offset;
// uniform float cloud_shadow_coverage;
// uniform float cloud_shadow_darkness;
// 2. #include this file
// 3. In light():
// float shadow = sample_cloud_shadow(
// (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).xyz,
// LIGHT);
// LIGHT_COLOR *= shadow;
//
// CloudSystem.gd provides apply_cloud_shadow_params(mat) to set the uniforms.
#include "res://addons/sky3d_extended/shaders/noise.gdshaderinc"
// Simplified fBM matching the cloud system's procedural noise
float cloud_shadow_fbm(vec2 uv) {
float total = 0.0;
float amplitude = 1.0;
float frequency = 1.0;
float max_amp = 0.0;
for (int i = 0; i < 4; i++) {
total += amplitude * value_noise(uv * frequency);
max_amp += amplitude;
amplitude *= 0.5;
frequency *= 2.02;
}
return total / max_amp;
}
// Sample cloud shadow at a world position given the directional light vector.
// Returns 1.0 = fully lit, (1.0 - darkness) = fully shadowed.
float sample_cloud_shadow(vec3 world_pos, vec3 light_dir,
float shadow_altitude, float shadow_scale,
vec2 wind_offset, float shadow_coverage, float shadow_darkness) {
// Ray-plane intersection: project world_pos onto cloud plane along light direction
float t = (shadow_altitude - world_pos.y) / max(light_dir.y, 0.001);
vec2 cloud_uv = (world_pos.xz + light_dir.xz * t) * shadow_scale + wind_offset;
float noise_val = cloud_shadow_fbm(cloud_uv);
// Coverage threshold with soft edge matching cloud_main.gdshader logic
float shadow = smoothstep(1.0 - shadow_coverage, 1.0 - shadow_coverage + 0.15, noise_val);
return mix(1.0, 1.0 - shadow_darkness, shadow);
}