80 lines
2.3 KiB
Plaintext
80 lines
2.3 KiB
Plaintext
// 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<float4> 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<float4> 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);
|
|
}
|