 // Rendering  parameters
 uniform float radianceClamp;
 uniform float skipProbability;
+uniform float shadowStrength;
 uniform bool maxStepsIsMiss;
 
 // Length scales
-uniform float lengthScale;                      // UPLOAD!
 uniform float minLengthScale;
 uniform float maxLengthScale;
 

                float sunPdf;
                vec3 woutputW;
                vec3 Li = sampleSunAtSurface(basis, rnd, woutputW, sunPdf);
                vec3 TrToLight = transmittanceOverSegment(pW_hit+dPw, woutputW, maxLengthScale);
                if (averageComponent(Li) > RADIANCE_EPSILON)
                    Ldirect += f * TrToLight * Li / max(PDF_EPSILON, sunPdf) * abs(dot(woutputW, nW));
            }
#ifdef HAS_ATMOSPHERE
            vec3 TrToHit = transmittanceOverFreeSegment(primaryStart, primaryDir, rayLength);
#else
            vec3 TrToHit = vec3(1.0);
#endif
            L += TrToHit * Ldirect;

#ifdef HAS_ATMOSPHERE
            // Add term for single-scattering in the homogeneous atmosphere over the segment up to the closest hit
            vec3 Lscatter = atmosphericInscatteringRadiance(primaryStart, primaryDir, rayLength, rnd);
            L += Lscatter;
#endif

#ifdef HAS_VOLUME_EMISSION
            // Add volumetric emission at the surface point, if present (treating it as an isotropic radiance field)
            L += TrToHit * VOLUME_EMISSION_EVAL(pW_hit);
#endif
        }

        // Miss logic
        else
        {
            vec3 TrToInfinity = vec3(1.0);
#ifdef HAS_ATMOSPHERE
            // Add term for single-inscattering in the homogeneous atmosphere over the segment to infinity
            vec3 Lscatter = atmosphericInscatteringRadiance(primaryStart, primaryDir, maxLengthScale, rnd);
            L += Lscatter;
            TrToInfinity = transmittanceOverFreeSegment(primaryStart, primaryDir, maxLengthScale);
#endif
            if (envMapVisible)      L += TrToInfinity * environmentRadiance(primaryDir);
            if (sunVisibleDirectly) L += TrToInfinity * sunRadiance(primaryDir);
        }

    } // sample n of __MAX_SAMPLES_PER_FRAME__

    L /= float(__MAX_SAMPLES_PER_FRAME__);

    vec3 XYZ = rgbToXyz(L);

    // Write updated radiance and sample count
    vec4 oldL = texture(Radiance, vTexCoord);

#endif

        // Raycast to first hit point
        vec3 pW;
        vec3 woW = -primaryDir;
        int hitMaterial;
        bool hit = traceRay(primaryStart, primaryDir, pW, hitMaterial, maxLengthScale);
        if (hit)
        {
            // Compute normal at hit point
            vec3 nW = normal(pW, hitMaterial);
            Basis basis = makeBasis(nW);
#ifdef HAS_SURFACE_NORMALMAP
            nW = perturbNormal(pW, basis, hitMaterial);
            basis = makeBasis(nW);
#endif

            // Compute diffuse BSDF
            vec3 f = SURFACE_DIFFUSE_REFL_RGB(pW, nW, woW) / M_PI;

            // Compute direct lighting
            vec3 Ldirect = vec3(0.0);
