layers_environment_shaders_CloudsBlurShader.js

/**kawase blur pass**/
const CloudsBlurShader = {
	vertexShader: () =>/* glsl */`
	precision highp float;
	precision highp int;

	varying vec2 vUv;
	
	void main() {
		vUv = uv;
		gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
	}`,

	// a mostly basic kawase blur but it avoids bluring samples together when the depth is very different excepth when the depth is very large.
	// it also adds some randomness to the samples positions to remove the resulting banding

	fragmentShader: () => {

		let code = /* glsl */`
		precision highp float;

		#include <packing>

		uniform sampler2D image;
		uniform sampler2D tDepth;
		uniform sampler2D cloudsDepth;
		uniform sampler2D noise2D;
		uniform vec2 offset;
		uniform float preserveMaxOpacity;
		uniform float cameraNear;
		uniform float cameraFar;
		uniform float ldf;
		varying vec2 vUv;

		
			
		float readDepth( sampler2D depthSampler, vec2 coord ) {
			vec4 fragCoord = texture2D( depthSampler, coord );
			float invViewZ = exp2(fragCoord.x / (ldf * 0.5)) - 1.0;
			return mix(cameraNear, cameraFar,viewZToOrthographicDepth( -invViewZ, cameraNear, cameraFar ));


			//return mix(cameraNear, cameraFar,viewZToOrthographicDepth(1.0 - exp2(texture2D(depthSampler, coord).x * log(cameraFar + 1.0) / log(2.0)),cameraNear, cameraFar));
		}

		
		float toRealDepth(float normalizedCloudDepth ){
			return mix(cameraNear, cameraFar, normalizedCloudDepth);
			//return (normalizedCloudDepth*(cameraFar-cameraNear))+cameraNear;
		}

		float whiteNoise(vec2 uv) {
    		return fract(sin(dot(uv.xy ,vec2(12.9898,78.233))) * 43758.5453123);
		}
		
		void main() {

    vec4 center = texture2D(image, vUv);
    if (center.a == 0.0) return;

    // Fetch cloud depth and generate noise
    float cloudD = texture2D(cloudsDepth, vUv).x;
    float noiseX = whiteNoise(vUv * 4.0);
    float noiseY = whiteNoise(vUv * 4.0 + vec2(0.0, 1.0));
    vec2 noiseVec = vec2(noiseX, noiseY);

    // Compute scaling factors
    float cloudFactor = cloudD * 4.0;
    float alphaFactor = center.a * center.a;
    float scaleFactor = clamp(cloudFactor * alphaFactor, 0.5, 1.0);

    // Calculate random offset
    vec2 offsetRand = offset * scaleFactor * (0.5 + noiseVec);

    // Compute sample coordinates
    vec2 uv1 = vUv + offsetRand;
    vec2 uv2 = vUv - offsetRand;
    vec2 uv3 = vUv + offsetRand * vec2(1.0, -1.0);
    vec2 uv4 = vUv + offsetRand * vec2(-1.0, 1.0);

    // Fetch neighboring samples
    vec4 a = texture2D(image, uv1);
    vec4 b = texture2D(image, uv2);
    vec4 c = texture2D(image, uv3);
    vec4 d = texture2D(image, uv4);

    // Initialize the output color
    gl_FragColor = vec4(0.0);

    // Define a function-like macro for repeated calculations (optional)
    #define APPLY_SAMPLE(sampleColor) { \
        float diff = 1.0 - abs(center.a - sampleColor.a); \
        float w = diff * diff * diff * diff; \
        gl_FragColor += 0.25 * mix(center, sampleColor, w); \
    }

    // Apply samples
    APPLY_SAMPLE(a);
    APPLY_SAMPLE(b);
    APPLY_SAMPLE(c);
    APPLY_SAMPLE(d);

    // Preserve the alpha channel
    gl_FragColor.a = center.a;
}`;




		return code;
	}
}
export { CloudsBlurShader };