 
     // R: Perlin-Worley noise
     // G,B,A: Worley noises at increasing frequencies
-    vec4 baseNoises = texture(shapeNoise, samplePos);
+    vec4 baseNoises = textureLod(shapeNoise, samplePos, lod);
     float lowFreqFBM = dot(vec3(0.625, 0.25, 0.125), baseNoises.yzw);
 
     // #todo: baseCloud values are too high
     float baseCloud = baseNoises.x - 0.92;
 
-    vec3 detailNoises = texture(erosionNoise, CURLINESS * samplePos2).xyz;
+    vec3 detailNoises = textureLod(erosionNoise, CURLINESS * samplePos2, lod).xyz;
 
     result.x = saturate(remap(baseCloud, -(1.0 - lowFreqFBM), 1.0, 0.0, 1.0));
     result.y = dot(vec3(0.625, 0.25, 0.125), detailNoises);
     return result;
 }
 
-float sampleCloud(vec3 P) {
+float sampleCloud(vec3 P, float lod) {
     vec4 weatherData = sampleWeather(P);
 
     float cloudCoverage = weatherData.x;
 
 #if DEBUG_MODE == DEBUG_MODE_NO_NOISE || DEBUG_MODE == DEBUG_MODE_WEATHER
-    return cloudCoverage * getDensityForCloud(getHeightFraction(P), 0.5);
+    return cloudCoverage * getDensityForCloud(getHeightFraction(P), 1.0);
+    //return cloudCoverage * getCumulusGradient(P);
     //return cloudCoverage;
 #endif
 
-    vec2 cloudNoiseSamples = sampleCloudShapeAndErosion(P);
+    vec2 cloudNoiseSamples = sampleCloudShapeAndErosion(P, lod);
 
     float baseCloud = cloudNoiseSamples.x;
     float heightFraction = getHeightFraction(P);


    bool useDebugColor = false;

    const int numSteps = 64;
    const int inscatSteps = 6;
    
    float cosTheta = dot(camera.direction, -sunDir);

        vec3 Lem = T * (0.05 * vec3(0.13, 0.13, 0.27));

        // In-scattering
        vec3 SUN_RADIANCE = 0.4 * vec3(0.9, 0.8, 1.1); // #todo
        vec3 Lsc = T * sigma_s * phaseFn * (SUN_RADIANCE * TL);

        // #todo: Multiply with cloudDensity?
