#include #include using namespace metal; struct NTSCParams { float source_width; float source_height; float a_value; float b_value; float cc_value; float scan_time; float notch_width; float y_freq; float i_freq; float q_freq; float _pad0; float _pad1; }; struct main0_out { float4 FragColor [[color(0)]]; }; struct main0_in { float2 v_uv [[user(locn0)]]; }; fragment main0_out main0(main0_in in [[stage_in]], constant NTSCParams& u [[buffer(0)]], texture2d Source [[texture(0)]], sampler SourceSmplr [[sampler(0)]]) { main0_out out = {}; float2 source_dims = float2(u.source_width, u.source_height); float2 PValueSourceTexel = float2(1.0, 0.0) / source_dims; float2 C0 = in.v_uv + (PValueSourceTexel * float2(0.0)); float2 C1 = in.v_uv + (PValueSourceTexel * float2(0.25, 0.0)); float2 C2 = in.v_uv + (PValueSourceTexel * float2(0.5, 0.0)); float2 C3 = in.v_uv + (PValueSourceTexel * float2(0.75, 0.0)); float4 Cx = float4(C0.x, C1.x, C2.x, C3.x); float4 Cy = float4(C0.y, C1.y, C2.y, C3.y); float4 Texel0 = Source.sample(SourceSmplr, C0); float4 Texel1 = Source.sample(SourceSmplr, C1); float4 Texel2 = Source.sample(SourceSmplr, C2); float4 Texel3 = Source.sample(SourceSmplr, C3); float4 HPosition = Cx; float4 VPosition = Cy; float4 Y = float4(dot(Texel0, float4(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625, 0.0)), dot(Texel1, float4(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625, 0.0)), dot(Texel2, float4(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625, 0.0)), dot(Texel3, float4(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625, 0.0))); float4 I = float4(dot(Texel0, float4(0.595715999603271484375, -0.2744530141353607177734375, -0.3212629854679107666015625, 0.0)), dot(Texel1, float4(0.595715999603271484375, -0.2744530141353607177734375, -0.3212629854679107666015625, 0.0)), dot(Texel2, float4(0.595715999603271484375, -0.2744530141353607177734375, -0.3212629854679107666015625, 0.0)), dot(Texel3, float4(0.595715999603271484375, -0.2744530141353607177734375, -0.3212629854679107666015625, 0.0))); float4 Q = float4(dot(Texel0, float4(0.211456000804901123046875, -0.52259099483489990234375, 0.311134994029998779296875, 0.0)), dot(Texel1, float4(0.211456000804901123046875, -0.52259099483489990234375, 0.311134994029998779296875, 0.0)), dot(Texel2, float4(0.211456000804901123046875, -0.52259099483489990234375, 0.311134994029998779296875, 0.0)), dot(Texel3, float4(0.211456000804901123046875, -0.52259099483489990234375, 0.311134994029998779296875, 0.0))); float W = (6.283185482025146484375 * u.cc_value) * u.scan_time; float WoPI = W / 3.1415927410125732421875; float HOffset = u.a_value / WoPI; float VScale = (u.b_value * source_dims.y) / WoPI; float4 T = (HPosition + float4(HOffset)) + (VPosition * float4(VScale)); float4 TW = T * W; out.FragColor = (Y + (I * cos(TW))) + (Q * sin(TW)); return out; }