// ============================================================================
// RIMLIGHT CALCULATION
// ============================================================================
#ifndef RIMLIGHT_GLSL
#define RIMLIGHT_GLSL

// Linearizes depth for accurate distance calculations.
float linearizeDepthRim(float d, float near, float far) {
    return (near * far) / (far - d * (far - near));
}

float getRimLight(sampler2D depthTex, vec2 uv, vec2 texelSize, float near, float far) {
    float centerDepth = texture2D(depthTex, uv).r;
    if (centerDepth >= 1.0) return 0.0; 

    float zC = linearizeDepthRim(centerDepth, near, far);
    
    // Fades out the rimlight in the far distance.
    float distanceFade = clamp(1.0 - (zC / RIM_MAX_DISTANCE), 0.0, 1.0);
    if (distanceFade <= 0.0) return 0.0;

    // Defines cardinal offsets for edge detection.
    vec2 offX = vec2(RIM_THICKNESS, 0.0) * texelSize;
    vec2 offY = vec2(0.0, RIM_THICKNESS) * texelSize;

    // Reads surrounding depth samples in a cross pattern.
    float d1 = linearizeDepthRim(texture2D(depthTex, uv + offX).r, near, far);
    float d2 = linearizeDepthRim(texture2D(depthTex, uv - offX).r, near, far);
    float d3 = linearizeDepthRim(texture2D(depthTex, uv + offY).r, near, far);
    float d4 = linearizeDepthRim(texture2D(depthTex, uv - offY).r, near, far);

    // Laplacian depth detects true silhouettes and ignores flat slopes.
    float laplacianDepth = (d1 + d2 + d3 + d4) - (4.0 * zC);

    // Scales thresholds by distance to maintain consistent line thickness.
    float adaptiveThreshold = RIM_DEPTH_THRESHOLD * zC * 0.15;

    // Applies smoothstep for clean and stylized toon edges.
    float edgeMask = smoothstep(adaptiveThreshold, adaptiveThreshold * 2.5, laplacianDepth);
    
    return edgeMask * distanceFade;
}
#endif