Last active
February 21, 2026 02:21
-
-
Save bunkbail/5cc0fd5e1d8196557b7c92af2b53dfe4 to your computer and use it in GitHub Desktop.
CFL-Lite v1.2: A highly optimized Chroma From Luma Upscaler
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // CFL-Lite v1.2 - A highly optimized Chroma From Luma Upscaler | |
| // Author: bunkbail | |
| // License: MIT | |
| // | |
| // An adaptive chroma upscaling shader that reconstructs high-resolution color | |
| // information from high-resolution luma using local linear regression. | |
| // | |
| // Features: | |
| // - Linear regression-based chroma prediction | |
| // - Static ridge regularization optimized for SDR and HDR | |
| // - Neighbor clamping for anti-ringing | |
| // - R²-based confidence blending with bilinear fallback | |
| // - Per-channel confidence for optimal prediction utilization | |
| // - Bilinear-weighted regression for spatial consistency | |
| // - Outlier-robust covariance for compression artifact immunity | |
| // - Adaptive confidence floor based on local variance | |
| // - Proper linearization for both SDR (x^2) and HDR (x^4) | |
| // - Deferred chroma sampling for bandwidth optimization | |
| // - Early exit for flat luma areas | |
| // | |
| // Usage: Place in your mpv shaders directory and load with: | |
| // glsl-shaders="~~/shaders/cfl-lite.glsl" | |
| //!HOOK CHROMA | |
| //!BIND HOOKED | |
| //!BIND LUMA | |
| //!WIDTH LUMA.w | |
| //!HEIGHT LUMA.h | |
| //!WHEN CHROMA.w LUMA.w < | |
| //!OFFSET ALIGN | |
| //!DESC CFL-Lite v1.2 | |
| // ============================================================================ | |
| // FEATURE TOGGLES | |
| // ============================================================================ | |
| // HDR Support | |
| // 0 = SDR (Applies x^2 linearization for gamma 2.0 approximation) | |
| // 1 = HDR (Applies x^4 linearization for PQ approximation) | |
| // Should match FSR_HDR setting in FSR-Lite for consistent processing. | |
| #ifndef CFL_HDR | |
| #define CFL_HDR 0 | |
| #endif | |
| // ============================================================================ | |
| // TUNABLE PARAMETERS | |
| // ============================================================================ | |
| // Ridge regularization for linear regression | |
| // Prevents division by zero when luma variance is near-zero. | |
| // Scaled for weighted variance (range ~0 to 0.25 instead of ~0 to 1). | |
| #define RIDGE_LAMBDA 2.5e-5 | |
| // Base confidence floor for R² correlation | |
| // R² values below this are treated as "no meaningful correlation". | |
| // Actual floor adapts based on local variance (see adaptive confidence). | |
| #define CONFIDENCE_FLOOR 0.04 | |
| // Luma variance threshold for early exit | |
| // Below this variance, the local area is considered flat and CFL is skipped. | |
| // Scaled for weighted variance (range ~0 to 0.25 instead of ~0 to 1). | |
| #define LUMA_VARIANCE_THRESHOLD 0.00025 | |
| // Epsilon for numerical safety | |
| #define EPSILON 1.0e-12 | |
| // ============================================================================ | |
| // LINEARIZATION FUNCTIONS | |
| // ============================================================================ | |
| #if CFL_HDR | |
| // HDR: Fast approximation for PQ linearization (x^4) | |
| // PQ has a steeper curve, x^4 is a reasonable approximation | |
| vec4 ToLin4(vec4 v) { vec4 s = v * v; return s * s; } | |
| vec2 ToLin2(vec2 v) { vec2 s = v * v; return s * s; } | |
| float ToLin1(float v) { float s = v * v; return s * s; } | |
| // HDR: Delinearization (sqrt(sqrt(x))) | |
| vec2 ToGamma2(vec2 v) { return sqrt(sqrt(max(v, 0.0))); } | |
| #else | |
| // SDR: Fast approximation for Gamma 2.0 linearization (x^2) | |
| // Standard SDR uses gamma 2.2-2.4, x^2 is close enough for regression | |
| // Regression must be done in linear space for mathematically correct results | |
| vec4 ToLin4(vec4 v) { return v * v; } | |
| vec2 ToLin2(vec2 v) { return v * v; } | |
| float ToLin1(float v) { return v * v; } | |
| // SDR: Delinearization (sqrt(x)) | |
| vec2 ToGamma2(vec2 v) { return sqrt(max(v, 0.0)); } | |
| #endif | |
| // ============================================================================ | |
| // MAIN HOOK FUNCTION | |
| // ============================================================================ | |
| vec4 hook() { | |
| // ==================================================================== | |
| // SAMPLE COORDINATE CALCULATION | |
| // ==================================================================== | |
| highp vec2 pp = HOOKED_pos * HOOKED_size - vec2(0.5); | |
| highp vec2 fp = floor(pp); | |
| pp -= fp; | |
| // Bilinear weights for spatial blending | |
| vec2 w1 = 1.0 - pp; | |
| vec2 w2 = pp; | |
| vec4 weights = vec4(w1.x * w1.y, w2.x * w1.y, w1.x * w2.y, w2.x * w2.y); | |
| // ==================================================================== | |
| // DEFERRED SAMPLING: LUMA FIRST | |
| // ==================================================================== | |
| // Sample luma at 2x2 neighbors (needed for variance check) | |
| vec4 luma = vec4( | |
| LUMA_texOff(vec2(0.0, 0.0)).x, | |
| LUMA_texOff(vec2(1.0, 0.0)).x, | |
| LUMA_texOff(vec2(0.0, 1.0)).x, | |
| LUMA_texOff(vec2(1.0, 1.0)).x | |
| ); | |
| // Linearize for correct regression math | |
| luma = ToLin4(luma); | |
| // Calculate weighted mean and variance | |
| float lAvg = dot(luma, weights); | |
| vec4 lDiff = luma - lAvg; | |
| float lVar = dot(lDiff * lDiff, weights); | |
| // ==================================================================== | |
| // EARLY EXIT FOR FLAT AREAS (saves 4 chroma fetches) | |
| // ==================================================================== | |
| if (lVar < LUMA_VARIANCE_THRESHOLD) { | |
| // Flat area: return simple bilinear chroma | |
| vec2 cBilinear = ToLin2(HOOKED_tex(HOOKED_pos).xy); | |
| return vec4(ToGamma2(cBilinear), 0.0, 1.0); | |
| } | |
| // ==================================================================== | |
| // CHROMA SAMPLING (only for non-flat areas) | |
| // ==================================================================== | |
| // Sample chroma at 2x2 neighbors | |
| vec2 tTL = HOOKED_texOff(vec2(0.0, 0.0)).xy; | |
| vec2 tTR = HOOKED_texOff(vec2(1.0, 0.0)).xy; | |
| vec2 tBL = HOOKED_texOff(vec2(0.0, 1.0)).xy; | |
| vec2 tBR = HOOKED_texOff(vec2(1.0, 1.0)).xy; | |
| vec4 chromaU = vec4(tTL.x, tTR.x, tBL.x, tBR.x); | |
| vec4 chromaV = vec4(tTL.y, tTR.y, tBL.y, tBR.y); | |
| // Linearize for correct regression math | |
| chromaU = ToLin4(chromaU); | |
| chromaV = ToLin4(chromaV); | |
| vec2 tTL_lin = ToLin2(tTL); | |
| vec2 tTR_lin = ToLin2(tTR); | |
| vec2 tBL_lin = ToLin2(tBL); | |
| vec2 tBR_lin = ToLin2(tBR); | |
| // ==================================================================== | |
| // STATISTICAL ANALYSIS | |
| // ==================================================================== | |
| // Bilinear-weighted means: this IS the bilinear interpolant | |
| vec2 cAvg = vec2(dot(chromaU, weights), dot(chromaV, weights)); | |
| vec4 cDiffU = chromaU - cAvg.x; | |
| vec4 cDiffV = chromaV - cAvg.y; | |
| // Outlier-robust covariance via clamping | |
| vec4 lDiffClamped = clamp(lDiff, -2.0 * sqrt(max(lVar, EPSILON)), 2.0 * sqrt(max(lVar, EPSILON))); | |
| vec2 cov = vec2( | |
| dot(lDiffClamped * weights, cDiffU), | |
| dot(lDiffClamped * weights, cDiffV) | |
| ); | |
| vec2 cVar = vec2( | |
| dot(cDiffU * cDiffU, weights), | |
| dot(cDiffV * cDiffV, weights) | |
| ); | |
| // ==================================================================== | |
| // LINEAR REGRESSION WITH PER-CHANNEL ADAPTIVE SLOPE CLAMPING | |
| // ==================================================================== | |
| vec2 alpha = cov / (lVar + RIDGE_LAMBDA); | |
| // Optimized: single sqrt instead of sqrt/sqrt | |
| vec2 maxSlope = max(vec2(1.0), sqrt(max(cVar, vec2(EPSILON)) / max(lVar, EPSILON))); | |
| alpha = clamp(alpha, -maxSlope, maxSlope); | |
| // High-res luma for prediction | |
| float lHigh = ToLin1(LUMA_texOff(0.0).x); | |
| vec2 cPred = cAvg + alpha * (lHigh - lAvg); | |
| // ==================================================================== | |
| // ANTI-RINGING (NEIGHBOR CLAMPING) | |
| // ==================================================================== | |
| vec2 cMin = min(min(tTL_lin, tTR_lin), min(tBL_lin, tBR_lin)); | |
| vec2 cMax = max(max(tTL_lin, tTR_lin), max(tBL_lin, tBR_lin)); | |
| cPred = clamp(cPred, cMin, cMax); | |
| // ==================================================================== | |
| // CONFIDENCE CALCULATION | |
| // ==================================================================== | |
| // Per-channel R² correlation | |
| // Note: cov uses clamped lDiff while denominator uses unclamped lVar. | |
| // This intentionally underestimates R² near outliers, causing conservative | |
| // fallback to bilinear. This is safe behavior, not a bug. | |
| vec2 denom = max(vec2(lVar) * cVar, vec2(EPSILON)); | |
| vec2 corrSq = clamp((cov * cov) / denom, 0.0, 1.0); | |
| // Adaptive confidence floor: high variance = lower floor = trust CFL more | |
| float adaptiveFloor = CONFIDENCE_FLOOR / (1.0 + lVar * 10.0); | |
| vec2 conf = max(corrSq - adaptiveFloor, 0.0) / (1.0 - adaptiveFloor); | |
| // Optimized: sqrt instead of pow(x, 0.7) | |
| conf = sqrt(conf); | |
| // ==================================================================== | |
| // FINAL OUTPUT | |
| // ==================================================================== | |
| // Per-channel blending: conf=0 → bilinear (cAvg), conf=1 → CFL prediction | |
| vec2 cFinal = mix(cAvg, cPred, conf); | |
| cFinal = ToGamma2(cFinal); | |
| return vec4(cFinal, 0.0, 1.0); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment