vec3 GetColoredLightFog(vec3 nPlayerPos, vec3 translucentMult, float lViewPos, float lViewPos1, float dither, float vlFactor) {
    vec3 lightFog = vec3(0.0);

    float stepMult = 8.0;

    #ifdef CAVE_SMOKE
        float caveFactor = GetCaveFactor() * (1.0 - clamp01(isEyeInWater));
    #endif

    float maxDist = min(effectiveACTdistance * 0.5, far);
    int sampleCount = int(maxDist / stepMult + 0.001);
    vec3 traceAdd = nPlayerPos * stepMult;
    vec3 tracePos = traceAdd * dither;

    for (int i = 0; i < sampleCount; i++) {
        tracePos += traceAdd;

        float lTracePos = length(tracePos);
        if (lTracePos > lViewPos1) break;
        if (any(greaterThan(abs(tracePos * 2.0), vec3(voxelVolumeSize)))) break;

        vec3 voxelPos = SceneToVoxel(tracePos);
        voxelPos = clamp01(voxelPos / vec3(voxelVolumeSize));

        vec4 lightVolume = GetLightVolume(voxelPos);
        vec3 lightSample = lightVolume.rgb;

        #if defined END && END_CENTER_LIGHTING > 0 && MC_VERSION >= 10900 && defined END_CENTER_LIGHTING_AFFECT_BLOCKLIGHT
            vec3 endCenterCol = saturateColors(vec3(END_CENTER_LIGHTING_R, END_CENTER_LIGHTING_G, END_CENTER_LIGHTING_B), 1.1);
            vec3 endCenterPos = vec3(0.5, 60.5, 0.5) - (tracePos + cameraPositionBest);
            endCenterPos.y *= 0.66; // Make it a pill-shaped point light
            float rawDistance = length(endCenterPos);
            float endCenterLightDist = exp(-rawDistance * 0.62) * 100;
            lightSample = mix(lightSample, clamp01(saturateColors(endCenterCol, 1.3)), clamp01(endCenterLightDist) * (1.0 - vlFactor));
        #endif

        float lTracePosM = length(
            vec3(
                tracePos.x,
                #if COLORED_LIGHTING_INTERNAL <= 512
                    tracePos.y * 2.0,
                #elif COLORED_LIGHTING_INTERNAL == 768
                    tracePos.y * 3.0,
                #elif COLORED_LIGHTING_INTERNAL == 1024
                    tracePos.y * 4.0,
                #endif
                tracePos.z
            )
        );
        lightSample *= max0(1.0 - lTracePosM / maxDist);
        lightSample *= pow2(min1(lTracePos * 0.03125));

        #if DOOM_AND_GLOOM_FOG == 1
            lightSample *= max(0.02, 1.0 - lTracePos * 0.03);
            lightSample *= 2.0;
            lightSample *= vec3(1.2, 0.7, 0.3);  // reddish light cuts through fog better
        #elif defined MOD_DOOM_AND_GLOOM && (DOOM_AND_GLOOM_FOG == 0)
            lightSample *= max(0.02, 1.0 - lTracePos * 0.03 * doomAndGloomFog);
            lightSample *= 1.0 + doomAndGloomFog;
            lightSample *= mix(vec3(1.0), vec3(1.2, 0.7, 0.3), doomAndGloomFog);  // reddish light cuts through fog better
        #endif

        #ifdef CAVE_SMOKE
            if (caveFactor > 0.00001) {
                vec3 smokePos = 0.0025 * (tracePos + cameraPosition);
                vec3 smokeWind = frameTimeCounter * vec3(0.006, 0.003, 0.0);
                float smoke = Noise3D(smokePos + smokeWind)
                            * Noise3D(smokePos * 3.0 - smokeWind)
                            * Noise3D(smokePos * 9.0 + smokeWind);
                smoke = smoothstep1(smoke);
                lightSample *= mix(1.0, smoke * 16.0, caveFactor);
                lightSample += caveFogColor * pow2(smoke) * 0.05 * caveFactor;
            }
        #endif

        if (lTracePos > lViewPos) lightSample *= translucentMult;
        lightFog += lightSample;
    }

    #ifdef NETHER
        lightFog *= netherColor * 5.0;
    #endif

    lightFog *= 1.0 - maxBlindnessDarkness;
    lightFog = pow(lightFog / sampleCount, vec3(0.25));

    return lightFog;
}
