float noise_clouds_base_simple(vec3 p) {
    float Base = texture(blueNoiseTexture, p.xz * 0.00002).g;
    Base = smoothstep(0.55, 1, Base);
    return Base;
}

float noise_clouds_base(vec3 p) {
    float HeightNoise = texture(blueNoiseTexture, p.xz * 0.0001).r;
    float Base = texture(blueNoiseTexture, p.xz * 0.00002).g;
    Base = smoothstep(0.55, 1, Base);

    float HeightR = smoothstep(CLOUD_LOWER_PLANE + 20, CLOUD_UPPER_PLANE - HeightNoise * 100, p.y);
    HeightR = pow(HeightR, 0.5);
    float HeightFalloff = 1 - HeightR;
    return HeightFalloff * Base;
}

float noise_clouds(vec3 p) {
    float Base = noise_clouds_base(p);
    if (Base < 0.001) return 0;

    vec2 Wind = frameTimeCounter * vec2(2, 3.75);

    vec2 D = vec2(texture(noisetex, (p.xy + Wind) * 0.0001).g, texture(noisetex, (p.xz + Wind) * 0.0001).g);
    vec3 Displacement = vec3(D.x, D.y, 1 - (D.x * D.x + D.y * D.y)) * 0.05;
    float Detail = 1 - texture(worleyNoiseTexture, p / vec3(256, 32, 256) * 1.5 + Displacement).r * 0.5;
    Detail *= 1 - texture(worleyNoiseTexture, p / vec3(256, 32, 256) * 0.75 + Displacement + 0.33).r * 0.75;
    Detail *= 1 - texture(worleyNoiseTexture, p / vec3(256, 32, 256) * 0.33 + Displacement + 0.5).r;

    return clamp(Base - Detail * 0.3, 0, 1);
}

vec3 hash3(vec3 p) {
    p = vec3(dot(p, vec3(127.1, 311.7, 74.7)), dot(p, vec3(269.5, 183.3, 246.1)), dot(p, vec3(113.5, 271.9, 124.6)));
    return fract(sin(p) * 43758.5453);
}
vec2 hash2(vec2 p) {
    p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));
    return fract(sin(p) * 43758.5453);
}
float hash3D(vec3 p) {
    vec3 h = hash3(p);
    return fract(h.x + h.y * 1e-1 + h.z * 1e-2);
}

// https://www.shadertoy.com/view/4ssfWM
float bayer8(vec2 a) {
    uvec2 b = uvec2(a);
    uint c = (b.x ^ b.y) << 1u;
    return float(
        ((c & 8u | b.y & 4u) >> 2u) |
            ((c & 4u | b.y & 2u) << 1u) |
            ((c & 2u | b.y & 1u) << 4u) //15 ops
    ) / 8. / 8.;
}

float ign(vec2 Pos) {
    float FrameMod = frameCounter % 64;
    Pos += 5.588238f * FrameMod;
    return fract(52.9829189 * fract(0.06711056 * Pos.x + 0.00583715 * Pos.y));
}

vec4 blue_noise(vec2 Pos) {
    vec4 Noise = texelFetch(blueNoiseTexture, ivec2(Pos) & 255, 0);

    Noise = fract(Noise + 1.61803398875 * frameCounter); // Animate

    return Noise;
}

float dither(vec2 Pos) {
    // Interleaved gradient noise
    return ign(Pos);

    // Use bayer dither when TAA is disabled because it's more visually pleasing
    return bayer8(Pos);
}
