#ifndef INCLUDE_CLOUD_SHADOWS
    #define INCLUDE_CLOUD_SHADOWS

    #include "/lib/shaderSettings/cloudsAndLighting.glsl"
    #include "/lib/shaderSettings/clouds.glsl"

    #ifdef CLOUDS_REIMAGINED
        #include "/lib/atmospherics/clouds/cloudCoord.glsl"
    #endif

    float GetCloudShadow(vec3 playerPos) {
        #ifndef OVERWORLD
            return 1.0;
        #endif

        float cloudShadow = 1.0;

        vec3 worldPos = playerPos + cameraPosition;
        #if defined DO_PIXELATION_EFFECTS && defined PIXELATED_SHADOWS
            //worldPos = playerPosPixelated + cameraPosition; // Disabled for now because cloud shadows are too soft to notice pixelation
        #endif

        #ifdef CLOUDS_REIMAGINED
            float EdotL = dot(eastVec, lightVec);
            float EdotLM = tan(acos(EdotL));

            #if SUN_ANGLE != 0
                float NVdotLM = tan(acos(dot(northVec, lightVec)));
            #endif

            float distToCloudLayer1 = cloudAlt1i - worldPos.y;
            vec3 cloudOffset1 = vec3(distToCloudLayer1 / EdotLM, 0.0, 0.0);
            #if SUN_ANGLE != 0
                cloudOffset1.z += distToCloudLayer1 / NVdotLM;
            #endif
            vec2 cloudPos1 = GetRoundedCloudCoord(ModifyTracePos(worldPos + cloudOffset1, cloudAlt1i).xz, CLOUD_SHADOW_ROUNDNESS);

            #ifndef COMPOSITE
                float cloudSample = texture2D(gaux4, cloudPos1).b;
            #else
                float cloudSample = texture2D(cloudWaterTex, cloudPos1).b;
            #endif
            cloudSample *= clamp(distToCloudLayer1 * 0.1, 0.0, 1.0);

            #ifdef DOUBLE_REIM_CLOUDS
                float distToCloudLayer2 = cloudAlt2i - worldPos.y;
                vec3 cloudOffset2 = vec3(distToCloudLayer2 / EdotLM, 0.0, 0.0);
                #if SUN_ANGLE != 0
                    cloudOffset2.z += distToCloudLayer2 / NVdotLM;
                #endif
                vec2 cloudPos2 = GetRoundedCloudCoord(ModifyTracePos(worldPos + cloudOffset2, cloudAlt2i).xz, CLOUD_SHADOW_ROUNDNESS);

                #ifndef COMPOSITE
                    float cloudSample2 = texture2D(gaux4, cloudPos2).b;
                #else
                    float cloudSample2 = texture2D(cloudWaterTex, cloudPos2).b;
                #endif
                cloudSample2 *= clamp(distToCloudLayer2 * 0.1, 0.0, 1.0);

                cloudSample = 1.0 - (1.0 - cloudSample) * (1.0 - cloudSample2);
            #endif

            cloudSample *= sqrt3(1.0 - abs(EdotL));
            cloudShadow = 1.0 - 0.85 * cloudSample;
        #else
            vec2 csPos = worldPos.xz + worldPos.y * 0.25;
            float wind = 4.0;
            #if CLOUD_SPEED_MULT == 100
                #define CLOUD_SPEED_MULT_M CLOUD_SPEED_MULT * 0.01
                wind *= syncedTime;
            #else
                #define CLOUD_SPEED_MULT_M CLOUD_SPEED_MULT * 0.01
                wind *= frameTimeCounter * CLOUD_SPEED_MULT_M;
            #endif
            #if CLOUD_DIRECTION == 1
                csPos.xy = csPos.yx;
            #endif
            csPos.y -= wind;
            csPos *= 0.000002 * CLOUD_UNBOUND_SIZE_MULT;

            vec2 shadowoffsets[8] = vec2[8](
                vec2( 0.0   , 1.0   ),
                vec2( 0.7071, 0.7071),
                vec2( 1.0   , 0.0   ),
                vec2( 0.7071,-0.7071),
                vec2( 0.0   ,-1.0   ),
                vec2(-0.7071,-0.7071),
                vec2(-1.0   , 0.0   ),
                vec2(-0.7071, 0.7071));
            float cloudSample = 0.0;
            for (int i = 0; i < 8; i++) {
                cloudSample += texture2DLod(noisetex, csPos + 0.005 * shadowoffsets[i], 0.0).b;
            }

            cloudShadow = smoothstep1(pow2(min1(cloudSample * 0.2)));
        #endif

        cloudShadow = mix(1.0, mix(cloudShadow, 1.0, NIGHT_CLOUD_UNBOUND_REMOVE * (1.0 - sunVisibility)), min1(CLOUD_TRANSPARENCY));
        cloudShadow = 1.0 - clamp01((1.0 - cloudShadow) * CLOUD_SHADOW_STRENGTH);

        #if CLOUD_SHADOW_FADE_DISTANCE > 0
            cloudShadow = mix(1.0, cloudShadow, clamp01(length(playerPos) / (CLOUD_SHADOW_FADE_DISTANCE * 10)));
        #endif

        return cloudShadow;
    }

#endif
