#define vc_cloudSize 0.003

float vc_shapeShadow(in vec3 pos) {
    const float bufferA = vc_depth*0.066;
    const float vc_marchLow = vc_lowEdge-bufferA;
    const float vc_marchHigh = vc_highEdge+bufferA;
    if (pos.y<vc_marchLow || pos.y>vc_marchHigh) return 0.0;

    const float bufferSpace = vc_depth*0.017;
    const float size        = vc_cloudSize;
    const float lowEdge     = vc_lowEdge+bufferSpace;
    const float highEdge    = vc_highEdge-bufferSpace;
    float tick              = animTick*0.03;
    vec3 windTick           = tick*vec3(1.0, -0.3, 0.0);

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

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

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

        shape      += (s_vcCoverage-1.0);

    #ifdef setBiomeEffects
        float biomeCoverage = 0.25*biomeCold+0.25*biomeHot+0.65*biomeDesert-0.15*biomeTropic+0.35*biomeSnow;
        shape      -= biomeCoverage;
    #endif

        shape      += wetness*0.34;

    float coverage  = linStep(shape*0.5+0.5-0.16, 0.38, 0.68);

    return coverage;
}

float getCloudShadow(in vec3 wpos, vec3 wdir, const int samples, const float density) {
    const float lowEdge     = vc_altitude-vc_depth/2+8.0;
    const float highEdge    = vc_altitude+vc_depth/2-8.0;

    float invSteps  = vc_depth/samples;
    float stepSize  = invSteps/abs(wdir.y);

    vec3 rpos   = wpos;

    vec3 increment  = wdir*stepSize;

    float fade      = smoothstep(abs(wdir.y), 0.125, 0.075);

    rpos += rpos.y <= vc_altitude ? wdir*(lowEdge-rpos.y) / wdir.y : vec3(0.0);

    float transmittance = 0.0;

    for (int i = 0; i<samples; ++i, rpos += increment) {
        float fade1   = 1.0-linStep(length(rpos-pos.camera), 20000.0, 25000.0)*0;
        if(fade1>0.0) transmittance += vc_shapeShadow(rpos)*fade1;
    }

    return exp2(-transmittance*0.03*density*invLog2*stepSize)*(1.0-fade)+fade;
}