float vc_getShadowShape(in vec3 pos) {
    float lowErode  = 1.0-sstep(pos.y, vc_lowEdge, vc_lowEdge+s_vcThickness*0.15);
    float highErode = sstep(pos.y, vc_lowEdge+s_vcThickness*0.17, vc_highEdge);
    float lowFade  = sstep(pos.y, vc_lowEdge, vc_lowEdge+s_vcThickness*0.07);
    float highFade = 1.0-sstep(pos.y, vc_highEdge-s_vcThickness*0.12, vc_highEdge);

    //pos.x          += pow3(sstep(pos.y, vc_lowEdge, vc_highEdge))*250;

    vec3 wind       = vec3(vc_tick)*vec3(1.0, 0.0, 0.0);

    #ifdef s_vcLocalCoverage
        float coverage  = getValue2D(pos.xz, 0.15*vc_size, wind.xz*0.0007);
            coverage    = sstep(coverage-wetness, 0.2, 0.9);
    #endif

    float shape     = fbm(pos*vc_size*vc_shapeSize, wind*0.8, 0.375, 2.2, 3);
        shape      -= 0.762;
        shape      += (s_vcCoverage-1.0)*0.2;
        shape      += wetness*0.04;
        #ifdef s_biomeDynamics
        shape      += vc_biomeCoverage*0.03;
        #endif

        shape      *= 1.5;

        shape      *= highFade;
        shape      -= lowErode*0.12*lowFade*s_vcCoverage;
        shape      -= highErode*0.22*highFade*s_vcCoverage;
        shape      *= lowFade;

    #ifdef s_vcLocalCoverage
        shape      -= coverage*0.25;
    #endif
        shape      += vc_daytimeCoverage;

    return max(shape, 0.0);
}

float vc_getShadow(in vec3 wpos, in vec3 wdir, const int samples, const float density) {
    float stepsize  = s_vcThickness/samples;
        stepsize    = stepsize/abs(wdir.y);

    vec3 rpos   = wpos;
    vec3 rstep  = wdir*stepsize;

    float fade  = sstep(abs(wdir.y), 0.1, 0.15);

    float transmittance     = 0.0;

    if (rpos.y <= s_vcAltitude) {
        rpos += wdir*(vc_lowEdge-rpos.y) / wdir.y;

        for (int i = 0; i<samples; ++i, rpos += rstep) {
            if (rpos.y<vc_lowEdge || rpos.y>vc_highEdge) continue;
            float dist  = length(rpos-pos.camera);
            float dfade = linStep(dist, 20000.0, 80000.0);
            if (finv(dfade)<0.002) continue;
            transmittance   += vc_getShadowShape(rpos)*sqrt(finv(dfade))*sqrt(timeNoon+timeNight);
        }
    }
    return exp2(-transmittance*density*0.25*invLog2*stepsize)*fade+finv(fade)
    #ifdef s_biomeDynamics
    *vcData.y
    #endif
    ;
}