float vpGetDensity(vec3 pos)
{
    float height = exp(-max(pos.y - cameraPosition.y, 0.0) * VP_VOL_HEIGHT_FALLOFF);

float noise = texture2D(colortex15, pos.xz * VP_VOL_NOISE_SCALE).r;

return height * mix(0.5, 1.0, noise);
}




vec3 vpVolumetricLight(
    vec3 worldPos,
    vec3 lightPosition,
    vec3 lightColor,
    float intensity)
{
    const int RAY_STEPS = VP_VOL_STEPS;

    vec3 light = vec3(0.0);

    float rayLength = min(distance(cameraPosition, worldPos),VP_VOL_DISTANCE);
    float stepLength = rayLength / float(RAY_STEPS);

    float transmittance = 1.0;

    vec3 lightDir = normalize(mat3(gbufferModelViewInverse) * lightPosition);

    for(int i = 0; i < RAY_STEPS; i++)
    {
        float t = (float(i) + 0.5) / float(RAY_STEPS);

        vec3 samplePos = mix(cameraPosition, worldPos, t);

        vec3 shadowCoord = vpVolumetricLightCoord(samplePos);

        vec3 shadow = vpGetShadow(shadowCoord);

        float density = vpGetDensity(samplePos);
        density *= mix(
            VP_VOL_NOISE_MIN,
            VP_VOL_NOISE_MAX,
            texture2D(colortex15, samplePos.xz * VP_VOL_NOISE_SCALE).r
        );

        vec3 viewDir = normalize(samplePos - cameraPosition);

        float mu = max(dot(viewDir, lightDir), 0.0);

        float phase = pow(mu, VP_VOL_PHASE_POWER);

        light += shadow * density * VP_VOL_DENSITY * phase * transmittance * stepLength;

        transmittance *= exp(-density * stepLength * VP_VOL_EXTINCTION);
    }

    return lightColor * intensity * light / float(RAY_STEPS);
}
