// Source-of-truth shader in Slang. // The current OpenGL sample still runs the checked-in GLSL fallback because it uses // legacy fixed-function texture coordinates in its fragment stage. struct FragmentInput { float4 position : SV_Position; float2 texCoord : TEXCOORD0; }; Texture2D UYVYtex; float4 rec709YCbCr2rgba(float Y, float Cb, float Cr, float a) { Y = (Y * 256.0 - 16.0) / 219.0; Cb = (Cb * 256.0 - 16.0) / 224.0 - 0.5; Cr = (Cr * 256.0 - 16.0) / 224.0 - 0.5; float r = Y + 1.5748 * Cr; float g = Y - 0.1873 * Cb - 0.4681 * Cr; float b = Y + 1.8556 * Cb; return float4(r, g, b, a); } float4 bilinear(float4 W, float4 X, float4 Y, float4 Z, float2 weight) { float4 m0 = lerp(W, Z, weight.x); float4 m1 = lerp(X, Y, weight.x); return lerp(m0, m1, weight.y); } void textureGatherYUV(Texture2D textureSampler, float2 tc, out float4 W, out float4 X, out float4 Y, out float4 Z) { uint width = 0; uint height = 0; textureSampler.GetDimensions(width, height); int2 tx = int2(tc * float2(width, height)); int2 tmin = int2(0, 0); int2 tmax = int2(int(width), int(height)) - int2(1, 1); W = textureSampler.Load(int3(tx, 0)); X = textureSampler.Load(int3(clamp(tx + int2(0, 1), tmin, tmax), 0)); Y = textureSampler.Load(int3(clamp(tx + int2(1, 1), tmin, tmax), 0)); Z = textureSampler.Load(int3(clamp(tx + int2(1, 0), tmin, tmax), 0)); } [shader("fragment")] float4 fragmentMain(FragmentInput input) : SV_Target { float2 tc = input.texCoord; float alpha = 0.7; float4 macro, macroU, macroR, macroUR; float4 pixel, pixelR, pixelU, pixelUR; textureGatherYUV(UYVYtex, tc, macro, macroU, macroUR, macroR); uint width = 0; uint height = 0; UYVYtex.GetDimensions(width, height); float2 off = frac(tc * float2(width, height)); if (off.x > 0.5) { pixel = rec709YCbCr2rgba(macro.a, macro.b, macro.r, alpha); pixelR = rec709YCbCr2rgba(macroR.g, macroR.b, macroR.r, alpha); pixelU = rec709YCbCr2rgba(macroU.a, macroU.b, macroU.r, alpha); pixelUR = rec709YCbCr2rgba(macroUR.g, macroUR.b, macroUR.r, alpha); } else { pixel = rec709YCbCr2rgba(macro.g, macro.b, macro.r, alpha); pixelR = rec709YCbCr2rgba(macro.a, macro.b, macro.r, alpha); pixelU = rec709YCbCr2rgba(macroU.g, macroU.b, macroU.r, alpha); pixelUR = rec709YCbCr2rgba(macroU.a, macroU.b, macroU.r, alpha); } return bilinear(pixel, pixelU, pixelUR, pixelR, off); }