From 2250cba35c04ef45c90ea35d33a8a25a886cd251 Mon Sep 17 00:00:00 2001 From: Acaki Date: Sun, 20 Jul 2025 18:27:59 +0800 Subject: [PATCH] feat: apply normalization fix to new shader --- VoidLink/Metal/Shaders-Linear.metal | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/VoidLink/Metal/Shaders-Linear.metal b/VoidLink/Metal/Shaders-Linear.metal index e7275a97..221d4f47 100644 --- a/VoidLink/Metal/Shaders-Linear.metal +++ b/VoidLink/Metal/Shaders-Linear.metal @@ -58,14 +58,27 @@ fragment float4 yuvToLinear(Vertex v [[ stage_in ]], texture2d luminancePlane [[ texture(0) ]], texture2d chrominancePlane [[ texture(1) ]]) { - float3 yuv = float3(luminancePlane.sample(s, v.texCoords).r, - chrominancePlane.sample(s, v.texCoords).rg); - yuv -= cscParams.offsets; + // 1. Sample the textures to get the raw float value from the GPU hardware. + float3 yuv_hardware_normalized = float3(luminancePlane.sample(s, v.texCoords).r, + chrominancePlane.sample(s, v.texCoords).rg); + + // 2. Reverse the hardware normalization to get back to the approximate 10-bit integer value. + // This reverses the server's (v_10bit << 6) and the hardware's (/ 65535.0) operations. + float y_10bit = (yuv_hardware_normalized.r * 65535.0) / 64.0; + float2 uv_10bit = (yuv_hardware_normalized.gb * 65535.0) / 64.0; + + // 3. Re-normalize the 10-bit value using the correct 1023.0 divisor that the CSC constants expect. + float3 yuv_corrected; + yuv_corrected.r = y_10bit / 1023.0; + yuv_corrected.gb = uv_10bit / 1023.0; + + // 4. Use this perfectly scaled YUV value for the color conversion. + yuv_corrected -= cscParams.offsets; float3 rgb; - rgb.r = dot(yuv, cscParams.matrix[0]); - rgb.g = dot(yuv, cscParams.matrix[1]); - rgb.b = dot(yuv, cscParams.matrix[2]); + rgb.r = dot(yuv_corrected, cscParams.matrix[0]); + rgb.g = dot(yuv_corrected, cscParams.matrix[1]); + rgb.b = dot(yuv_corrected, cscParams.matrix[2]); // Clamp RGB to valid range [0, 1] rgb = clamp(rgb, 0.0, 1.0);