OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / addons / sky3d_extended / shaders / cloud_shadow.gdshaderinc

53 lines · gdshaderinc ref:
// 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);
}