float lc_getCloudMap(in vec3 pos) {
    const float size        = 0.005;
    const float lowEdge     = lc_altitude-lc_depth/2+16.0;
    const float highEdge    = lc_altitude+lc_depth/2-16.0;
    float tick              = animTick*0.04;
    vec3 windTick           = tick*vec3(1.0, -0.3, 0.0);

        pos.xz          = rotateCoord(pos.xz, pi*0.1);

    float lowCoverage   = smoothstep(pos.y, lowEdge, lowEdge+lc_depth*0.12);
        lowCoverage     = pow2(1.0-lowCoverage);
    float highCoverage  = smoothstep(pos.y, highEdge-lc_depth*0.66, highEdge);
    float highFade      = smoothstep(pos.y, highEdge-lc_depth*0.2, highEdge);
        highFade        = 1.0-pow3(highFade);

    vec3 pos2           = pos.xyz;
        pos2.xz         = rotateCoord(pos2.xz, -pi*0.1);

    float shape     = worley2D(pos.xz, 2.8*size, windTick.xz)*2.0-1.0;
        shape      += perlin2D(pos2.xz, 4.2*size, windTick.xz*1.2)*0.75;

        shape      += (s_lcCoverage-1.0);

    #ifdef setBiomeEffects
        float biomeCoverage = 0.3*biomeCold+0.2*biomeHot+0.35*biomeDesert-0.2*biomeTropic+0.35*biomeSnow;
        shape      -= biomeCoverage;
    #endif
        shape      += wetness*0.75;

        shape      -= highCoverage*0.38+sqrt(1.0-highFade)*0.4;
        shape      -= lowCoverage*0.25;   
        shape       = shape*0.5+0.5;
        shape      *= highFade;

    float coverage  = linStep(shape, 0.52, 0.72);

    return coverage;
}

float lc_shape(in vec3 pos, in float cloudMap) {
    const float size        = 0.005;
    const float lowEdge     = lc_altitude-lc_depth/2+16.0;
    const float highEdge    = lc_altitude+lc_depth/2-16.0;
    float tick              = animTick*0.04;
    vec3 windTick           = tick*vec3(1.0, -0.3, 0.0);

    float heightGradient    = smoothstep(pos.y, lowEdge, highEdge);

        pos.x          += exp2(heightGradient)*30.0;
        pos.xz          = rotateCoord(pos.xz, pi*0.1);

    vec3 pos2           = pos.xyz;
        pos2.xz         = rotateCoord(pos2.xz, -pi*0.1);

    float offset        = noise3D(pos.xyz, 2.2*size, windTick.xyz*1.8)*3.0;

    #if s_lcDetail>=2
        offset         += noise3D(pos.xyz+offset*6.0, 6.6*size, windTick.xyz*2.1)*1.4;
    #endif

    vec3 pnoise         = (offset-vec3(0.5, 0.0, 0.1))*(14.0+heightGradient*2.0);

    vec3 posNoise       = pos+pnoise*1.0;
    vec3 pos2noise      = pos2+pnoise*1.3;

    float lowFade       = linStep(posNoise.y, lowEdge, lowEdge+lc_depth*0.06);
        lowFade         = pow2(lowFade);

    float shape     = 0.0;
        //shape      += worleyVolumeHQ(posNoise.xyz, 13.1*size, windTick.xyz*1.3)*0.7;
        shape       += getSlicedWorley(posNoise.xyz, 17.2*size, windTick.xyz*1.3)*0.72;

        #if s_lcDetail>=2
            //shape      += worleyVolume(pos2.xyz, 24.6*size, windTick.xyz*1.3)*0.4;
            shape       += getSlicedWorley(pos2noise.xyz, 28.6*size, windTick.xyz*1.3)*0.47;
        #endif

        #if s_lcDetail>=3
            shape      += noise3D(pos, 11.27*size, -windTick*1.7)*0.07;
            //shape      += noise3D(pos, 15.57*size, -windTick*2.2)*0.03;
        #endif

        shape      -= 0.1;
        shape      -= (1.0-sqrt(cloudMap))*1.25;

        shape      *= 1.7*sqrt(cloudMap);

/*
    float fadeMod   = max(s_lcCoverage, 1.0);
        fadeMod     = pow2(fadeMod)*0.5+fadeMod*0.5;
  */  
    float coverage  = shape;
        coverage   *= lowFade;

        coverage    = max(coverage*1.5, 0.0);

    return coverage*4.0;
}