#ifndef NOXARA_POTATO_MODE_GLSL
#define NOXARA_POTATO_MODE_GLSL

/*
 * Shared distance-quality ladder.
 * A factor of zero is guaranteed before POTATO_START_DISTANCE so nearby
 * rendering remains byte-for-byte on the original material paths.
 */
float getPotatoLodFactor(float viewDistance, float renderDistance) {
#if POTATO_MODE == 0
    return 0.0;
#else
    float startDistance = max(float(POTATO_START_DISTANCE), 1.0);
    float fullDistance = max(startDistance + 1.0, min(float(POTATO_FULL_DISTANCE), renderDistance));
    float lodFactor = smoothstep(startDistance, fullDistance, viewDistance);

    #if POTATO_MODE == 1
        // Balanced: retain full detail through most of the transition.
        return lodFactor * lodFactor;
    #elif POTATO_MODE == 2
        return lodFactor;
    #else
        // Maximum: simplify earlier, while retaining a smooth transition.
        return sqrt(lodFactor);
    #endif
#endif
}

float getPotatoMipLevel(float lodFactor) {
#if POTATO_MODE == 0 || DISTANT_TEXTURE_QUALITY == 0
    return 0.0;
#else
    #if DISTANT_TEXTURE_QUALITY == 1
        const float maximumMipBias = 0.75;
    #elif DISTANT_TEXTURE_QUALITY == 2
        const float maximumMipBias = 1.75;
    #else
        const float maximumMipBias = 3.0;
    #endif

    #if POTATO_MODE == 1
        return lodFactor * maximumMipBias * 0.75;
    #elif POTATO_MODE == 2
        return lodFactor * maximumMipBias;
    #else
        return lodFactor * maximumMipBias * 1.15;
    #endif
#endif
}

float getPotatoFeatureVisibility(float lodFactor, float fadeStart, float fadeEnd) {
    return 1.0 - smoothstep(fadeStart, fadeEnd, lodFactor);
}

float getPotatoMaterialVisibility(float lodFactor) {
#if POTATO_MODE == 0 || DISTANT_SHADING == 0
    return 1.0;
#elif DISTANT_SHADING == 1
    return getPotatoFeatureVisibility(lodFactor, 0.70, 0.96);
#elif DISTANT_SHADING == 2
    return getPotatoFeatureVisibility(lodFactor, 0.46, 0.78);
#else
    return getPotatoFeatureVisibility(lodFactor, 0.22, 0.52);
#endif
}

float getPotatoNormalVisibility(float lodFactor) {
#if POTATO_MODE == 0 || DISTANT_SHADING == 0
    return 1.0;
#elif DISTANT_SHADING == 1
    return getPotatoFeatureVisibility(lodFactor, 0.58, 0.90);
#elif DISTANT_SHADING == 2
    return getPotatoFeatureVisibility(lodFactor, 0.34, 0.70);
#else
    return getPotatoFeatureVisibility(lodFactor, 0.14, 0.42);
#endif
}

float getPotatoReflectionVisibility(float lodFactor) {
#if POTATO_MODE == 0 || DISTANT_SHADING == 0
    return 1.0;
#elif DISTANT_SHADING == 1
    return getPotatoFeatureVisibility(lodFactor, 0.52, 0.86);
#elif DISTANT_SHADING == 2
    return getPotatoFeatureVisibility(lodFactor, 0.28, 0.62);
#else
    return getPotatoFeatureVisibility(lodFactor, 0.08, 0.34);
#endif
}

float getPotatoShadowVisibility(float lodFactor) {
#if POTATO_MODE == 0 || DISTANT_SHADING == 0
    return 1.0;
#elif DISTANT_SHADING == 1
    return getPotatoFeatureVisibility(lodFactor, 0.74, 0.98);
#elif DISTANT_SHADING == 2
    return getPotatoFeatureVisibility(lodFactor, 0.52, 0.84);
#else
    return getPotatoFeatureVisibility(lodFactor, 0.30, 0.60);
#endif
}

float getPotatoWaterDetailVisibility(float lodFactor) {
#if POTATO_MODE == 0 || DISTANT_SHADING == 0
    return 1.0;
#elif DISTANT_SHADING == 1
    return getPotatoFeatureVisibility(lodFactor, 0.52, 0.86);
#elif DISTANT_SHADING == 2
    return getPotatoFeatureVisibility(lodFactor, 0.30, 0.68);
#else
    return getPotatoFeatureVisibility(lodFactor, 0.10, 0.40);
#endif
}

float getPotatoWindVisibility(float viewDistance) {
#if POTATO_MODE == 0 || DISTANT_SHADING == 0
    return 1.0;
#else
    // Keep the full wind quality up to the configured LOD boundary.  The
    // 64-block floor avoids distracting near-camera transitions in Maximum.
    float windStartDistance = max(64.0, float(POTATO_START_DISTANCE));
    float windEndDistance = max(windStartDistance + 16.0, float(POTATO_FULL_DISTANCE));
    return 1.0 - smoothstep(windStartDistance, windEndDistance, viewDistance);
#endif
}

vec3 applyPotatoColorQuantization(vec3 color, float lodFactor) {
#if POTATO_MODE == 3 && DISTANT_TEXTURE_QUALITY == 3
    if (lodFactor <= 0.72) return color;
    vec3 quantized = floor(color * 16.0 + 0.5) / 16.0;
    float quantization = smoothstep(0.72, 1.0, lodFactor) * 0.45;
    return mix(color, quantized, quantization);
#else
    return color;
#endif
}

#endif
