Get NTSC working in both bgfx and d3d, nw

master
therealmogminer@gmail.com 2016-03-29 01:56:19 +02:00
parent 0528efa10f
commit a4f615a14d
34 changed files with 80 additions and 63 deletions

View File

@ -7,14 +7,14 @@
}
],
"passes": [
{ "effect": "default\blit",
{ "effect": "default/blit",
"name": "Copy To Unstretched Texture",
"input": [
{ "sampler": "s_tex", "texture": "screen" }
],
"output": "temp"
},
{ "effect": "default\blit",
{ "effect": "default/blit",
"name": "Final Upscale",
"input": [
{ "sampler": "s_tex", "target": "temp" }

View File

@ -57,17 +57,18 @@
{ "type": "intenum", "name": "adjustments", "text": "Enable Adjustments", "default": 0, "max": 1, "min": 0, "step": 1, "scale": 1.0, "format": "%s", "screen": "any", "strings": [ "Off", "On" ] },
{ "type": "intenum", "name": "ntsc", "text": "Enable NTSC", "default": 0, "max": 1, "min": 0, "step": 1, "scale": 1.0, "format": "%s", "screen": "any", "strings": [ "Off", "On" ] },
{ "type": "float", "name": "a_value", "text": "NTSC A Value", "default": 50, "max": 100, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
{ "type": "float", "name": "b_value", "text": "NTSC B Value", "default": 50, "max": 100, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
{ "type": "float", "name": "cc_value", "text": "NTSC Color Carrier (Hz)", "default": 35795454, "max": 36795454, "min": 34795454, "step": 100, "scale": 0.0000001, "format": "%1.7f", "screen": "raster" },
{ "type": "float", "name": "p_value", "text": "NTSC Phase Offset", "default": 100, "max": 200, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
{ "type": "float", "name": "scan_time", "text": "NTSC Scanline Duration (uSec)", "default": 526, "max": 1500, "min": 1, "step": 1, "scale": 0.1, "format": "%3.1f", "screen": "raster" },
{ "type": "float", "name": "notch_width", "text": "NTSC Color Notch Filter Width", "default": 100, "max": 400, "min": 1, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
{ "type": "float", "name": "y_freq_response", "text": "NTSC Y Signal Bandwidth (Hz)", "default": 600, "max": 2100, "min": 1, "step": 10, "scale": 0.01, "format": "%2.2f", "screen": "raster" },
{ "type": "float", "name": "i_freq_response", "text": "NTSC I Signal Bandwidth (Hz)", "default": 120, "max": 2100, "min": 1, "step": 10, "scale": 0.01, "format": "%2.2f", "screen": "raster" },
{ "type": "float", "name": "q_freq_response", "text": "NTSC Q Signal Bandwidth (Hz)", "default": 60, "max": 2100, "min": 1, "step": 10, "scale": 0.01, "format": "%2.2f", "screen": "raster" },
{ "type": "float", "name": "jitter_offset", "text": "NTSC Frame Jitter Offset", "default": 0, "max": 200, "min": 1, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
{ "type": "intenum", "name": "ntsc", "text": "Enable NTSC", "default": 0, "max": 1, "min": 0, "step": 1, "scale": 1.0, "format": "%s", "screen": "any", "strings": [ "Off", "On" ] },
{ "type": "float", "name": "a_value", "text": "NTSC A Value", "default": 50, "max": 100, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
{ "type": "float", "name": "b_value", "text": "NTSC B Value", "default": 50, "max": 100, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
{ "type": "float", "name": "cc_value", "text": "NTSC Color Carrier (Hz)", "default": 35795454, "max": 36795454, "min": 34795454, "step": 100, "scale": 0.0000001, "format": "%1.7f", "screen": "raster" },
{ "type": "float", "name": "o_value", "text": "NTSC Outgoing Phase Offset", "default": 0, "max": 100, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
{ "type": "float", "name": "p_value", "text": "NTSC Incoming Phase Pixel Clock Scale", "default": 100, "max": 200, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
{ "type": "float", "name": "scan_time", "text": "NTSC Scanline Duration (uSec)", "default": 526, "max": 1500, "min": 1, "step": 1, "scale": 0.1, "format": "%3.1f", "screen": "raster" },
{ "type": "float", "name": "notch_width", "text": "NTSC Color Notch Filter Width", "default": 200, "max": 400, "min": 1, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
{ "type": "float", "name": "y_freq_response", "text": "NTSC Y Signal Bandwidth (Hz)", "default": 600, "max": 2100, "min": 1, "step": 10, "scale": 0.01, "format": "%2.2f", "screen": "raster" },
{ "type": "float", "name": "i_freq_response", "text": "NTSC I Signal Bandwidth (Hz)", "default": 120, "max": 2100, "min": 1, "step": 10, "scale": 0.01, "format": "%2.2f", "screen": "raster" },
{ "type": "float", "name": "q_freq_response", "text": "NTSC Q Signal Bandwidth (Hz)", "default": 60, "max": 2100, "min": 1, "step": 10, "scale": 0.01, "format": "%2.2f", "screen": "raster" },
{ "type": "float", "name": "jitter_offset", "text": "NTSC Frame Jitter Offset", "default": 0, "max": 200, "min": 1, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
{ "type": "color", "name": "red_ratios", "text": "Red Output from ", "default": [ 100, 0, 0 ], "max": [ 200, 200, 200 ], "min": [ 0, 0, 0 ], "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
{ "type": "color", "name": "grn_ratios", "text": "Green Output from ", "default": [ 0, 100, 0 ], "max": [ 200, 200, 200 ], "min": [ 0, 0, 0 ], "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "raster" },
@ -88,18 +89,18 @@
{ "type": "color", "name": "phosphor", "text": "Phosphor Persistence, ", "default": [ 55, 55, 55 ], "max": [ 100, 100, 100 ], "min": [ 0, 0, 0 ], "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "float", "name": "scanline_alpha", "text": "Scanline Amount", "default": 40, "max": 100, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "float", "name": "scanline_alpha", "text": "Scanline Amount", "default": 6, "max": 100, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "float", "name": "scanline_scale", "text": "Overall Scanline Scale", "default": 100, "max": 400, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "float", "name": "scanline_bright_scale", "text": "Scanline Brightness Scale", "default": 200, "max": 400, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "float", "name": "scanline_bright_offset", "text": "Scanline Brightness Offset", "default": 0, "max": 400, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "float", "name": "scanline_jitter_amount", "text": "Scanline Jitter Amount", "default": 0, "max": 400, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "float", "name": "scanline_height", "text": "Individual Scanline Scale", "default": 100, "max": 400, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "float", "name": "scanline_variation", "text": "Scanline Variation", "default": 100, "max": 400, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "float", "name": "shadow_alpha", "text": "Shadow Mask Amount", "default": 20, "max": 100, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "float", "name": "shadow_alpha", "text": "Shadow Mask Amount", "default": 40, "max": 100, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "vec2", "name": "shadow_uv_count", "text": "Shadow Mask Pixel Count ", "default": [ 12, 12 ], "max": [ 128, 128 ], "min": [ 1, 1 ], "step": 1, "scale": 1.0, "format": "%3f", "screen": "crt" },
{ "type": "vec2", "name": "shadow_uv_size", "text": "Shadow Mask UV Size ", "default": [ 500, 500 ], "max": [ 1000, 1000 ], "min": [ 0, 0 ], "step": 1, "scale": 0.001, "format": "%1.4f", "screen": "crt" },
{ "type": "vec2", "name": "shadow_uv_offset", "text": "Shadow Mask UV Offset ", "default": [ 0, 0 ], "max": [ 1000, 1000 ], "min": [ 0, 0 ], "step": 1, "scale": 0.001, "format": "%1.4f", "screen": "crt" },
{ "type": "float", "name": "humbar_alpha", "text": "Hum Bar Amount", "default": 0, "max": 100, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "float", "name": "humbar_alpha", "text": "Hum Bar Amount", "default": 5, "max": 100, "min": 0, "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "float", "name": "humbar_hertz_rate", "text": "Hum Bar Frequency", "default": 100, "max": 10000, "min": 0, "step": 1, "scale": 0.00001, "format": "%1.7f", "screen": "crt" },
{ "type": "color", "name": "floor", "text": "Signal Floor, ", "default": [ 5, 5, 5 ], "max": [ 100, 100, 100 ], "min": [ 0, 0, 0 ], "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
{ "type": "color", "name": "power", "text": "Signal Exponent, ", "default": [ 80, 80, 80 ], "max": [ 400, 400, 400 ], "min": [ 0, 0, 0 ], "step": 1, "scale": 0.01, "format": "%1.2f", "screen": "crt" },
@ -154,6 +155,11 @@
// oversample (optional): Double the internal size of this render target. Certain effects benefit from operating at a higher internal resolution. If you're not sure, leave it as false.
// values: true, false
// default: false
{
"name": "ntsc",
"mode": "guest",
"doublebuffer": true
},
{
"name": "guest",
"mode": "guest",
@ -169,6 +175,15 @@
// passes (required): The list of individual shaders to invoke, and any dynamic input parameters they need.
"passes": [
{
// See the pass after this one for a verbose explanation of each parameter.
"effect": "hlsl/blit",
"name": "NTSC Blit to bilinear-able target",
"input": [
{ "sampler": "s_tex", "texture": "screen" }
],
"output": "ntsc"
},
{
// effect (required): The name of the effect JSON file to load for this pass.
// value: Any valid JSON filename included in your shader chain, without the extension.
@ -246,13 +261,13 @@
//
// option (optional): The name of any MAME option, which will have its value fetched and used as the name of a PNG to load from the artwork directory.
// value: Any valid MAME INI option name.
{ "sampler": "s_tex", "texture": "screen" }
{ "sampler": "s_tex", "target": "ntsc" }
],
// output (required): The target to use as the output for this pass. Can be one of the named targets in "targets", or "output"
// or "previous" for one of two automatically-generated targets.
// value: Any valid ASCII string that names a target.
"output": "guest"
"output": "ntsc"
},
{ "effect": "hlsl/ntsc_decode",
"name": "NTSC Decode",
@ -264,6 +279,7 @@
{ "uniform": "u_a_value", "slider": "a_value" },
{ "uniform": "u_b_value", "slider": "b_value" },
{ "uniform": "u_cc_value", "slider": "cc_value" },
{ "uniform": "u_o_value", "slider": "o_value" },
{ "uniform": "u_scan_time", "slider": "scan_time" },
{ "uniform": "u_notch_width", "slider": "notch_width" },
{ "uniform": "u_y_freq_response", "slider": "y_freq_response" },
@ -274,7 +290,7 @@
{ "uniform": "u_jitter_amount", "parameter": "jitter" }
],
"input": [
{ "sampler": "s_tex", "target": "guest" }
{ "sampler": "s_tex", "target": "ntsc" }
],
"output": "guest"
},

View File

@ -7,14 +7,14 @@
}
],
"passes": [
{ "effect": "unfiltered\blit",
{ "effect": "unfiltered/blit",
"name": "Copy To Unstretched Texture",
"input": [
{ "sampler": "s_tex", "texture": "screen" }
],
"output": "temp"
},
{ "effect": "unfiltered\blit",
{ "effect": "unfiltered/blit",
"name": "Final Upscale",
"input": [
{ "sampler": "s_tex", "target": "temp" }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -49,7 +49,6 @@ struct PS_INPUT
uniform float2 ScreenDims;
uniform float2 SourceDims;
uniform float2 SourceRect;
VS_OUTPUT vs_main(VS_INPUT Input)
{
@ -108,10 +107,7 @@ static const int HalfSampleCount = SampleCount / 2;
float4 GetCompositeYIQ(float2 TexCoord)
{
float2 SourceTexelDims = 1.0f / SourceDims;
float2 SourceRes = SourceDims * SourceRect;
float2 PValueSourceTexel = float2(PValue, 0.0f) * SourceTexelDims;
float2 PValueSourceTexel = float2(PValue / SourceDims.x, 0.0f);
float2 C0 = TexCoord + PValueSourceTexel * OffsetX.x;
float2 C1 = TexCoord + PValueSourceTexel * OffsetX.y;
@ -124,8 +120,8 @@ float4 GetCompositeYIQ(float2 TexCoord)
float4 Texel2 = tex2D(DiffuseSampler, C2);
float4 Texel3 = tex2D(DiffuseSampler, C3);
float4 HPosition = Cx / SourceRect.x;
float4 VPosition = Cy / SourceRect.y;
float4 HPosition = Cx;
float4 VPosition = Cy;
float4 Y = float4(dot(Texel0, YDot), dot(Texel1, YDot), dot(Texel2, YDot), dot(Texel3, YDot));
float4 I = float4(dot(Texel0, IDot), dot(Texel1, IDot), dot(Texel2, IDot), dot(Texel3, IDot));
@ -135,7 +131,7 @@ float4 GetCompositeYIQ(float2 TexCoord)
float WoPI = W / PI;
float HOffset = (BValue + SignalOffset) / WoPI;
float VScale = (AValue * SourceRes.y) / WoPI;
float VScale = (AValue * SourceDims.y) / WoPI;
float4 T = HPosition + HOffset + VPosition * VScale;
float4 TW = T * W;
@ -149,10 +145,7 @@ float4 ps_main(PS_INPUT Input) : COLOR
{
float4 BaseTexel = tex2D(DiffuseSampler, Input.TexCoord);
float2 SourceTexelDims = 1.0f / SourceDims;
float2 SourceRes = SourceDims * SourceRect;
float TimePerSample = ScanTime / (SourceRes.x * 4.0f);
float TimePerSample = ScanTime / (SourceDims.x * 4.0f);
float Fc_y1 = (CCValue - NotchHalfWidth) * TimePerSample;
float Fc_y2 = (CCValue + NotchHalfWidth) * TimePerSample;
@ -175,23 +168,22 @@ float4 ps_main(PS_INPUT Input) : COLOR
float WoPI = W / PI;
float HOffset = (BValue + SignalOffset) / WoPI;
float VScale = (AValue * SourceRes.y) / WoPI;
float VScale = (AValue * SourceDims.y) / WoPI;
float4 YAccum = 0.0f;
float4 IAccum = 0.0f;
float4 QAccum = 0.0f;
float4 Cy = Input.TexCoord.y;
float4 VPosition = Cy / SourceRect.y;
float4 VPosition = Cy;
for (float i = 0; i < SampleCount; i += 4.0f)
{
float n = i - HalfSampleCount;
float4 n4 = n + NotchOffset;
float4 Cx = Input.TexCoord.x + SourceTexelDims.x * (n4 * 0.25f);
float4 HPosition = Cx / SourceRect.x;
float4 Cx = Input.TexCoord.x + (n4 * 0.25f) / SourceDims.x;
float4 HPosition = Cx;
float4 C = GetCompositeYIQ(float2(Cx.r, Cy.r));

View File

@ -43,8 +43,15 @@ void main()
vec4 one = vec4(1.0, 1.0, 1.0, 1.0);
vec4 two = vec4(2.0, 2.0, 2.0, 2.0);
vec4 four = vec4(4.0, 4.0, 4.0, 4.0);
int iSampleCount = 64;
vec4 SampleCount = vec4(64.0, 64.0, 64.0, 64.0);
vec4 HalfSampleCount = SampleCount / two;
vec4 TimePerSample = u_scan_time.xxxx / (u_source_dims.xxxx * four);
vec4 PI = vec4(3.1415927, 3.1415927, 3.1415927, 3.1415927);
vec4 PI2 = vec4(6.2831854, 6.2831854, 6.2831854, 6.2831854);
vec4 Fc_y1 = (u_cc_value.xxxx - u_notch_width.xxxx * onehalf) * TimePerSample;
vec4 Fc_y2 = (u_cc_value.xxxx + u_notch_width.xxxx * onehalf) * TimePerSample;
vec4 Fc_y3 = u_y_freq_response.xxxx * TimePerSample;
@ -52,9 +59,15 @@ void main()
vec4 Fc_q = u_q_freq_response.xxxx * TimePerSample;
vec4 Fc_i_2 = Fc_i * two;
vec4 Fc_q_2 = Fc_q * two;
const vec4 PI = vec4(3.1415927, 3.1415927, 3.1415927, 3.1415927);
const vec4 PI2 = vec4(6.2831854, 6.2831854, 6.2831854, 6.2831854);
vec4 Fc_y1_2 = Fc_y1 * two;
vec4 Fc_y2_2 = Fc_y2 * two;
vec4 Fc_y3_2 = Fc_y3 * two;
vec4 Fc_i_pi2 = Fc_i * PI2;
vec4 Fc_q_pi2 = Fc_q * PI2;
vec4 Fc_y1_pi2 = Fc_y1 * PI2;
vec4 Fc_y2_pi2 = Fc_y2 * PI2;
vec4 Fc_y3_pi2 = Fc_y3 * PI2;
vec4 PI2Length = PI2 / SampleCount;
vec4 W = PI2 * u_cc_value.xxxx * u_scan_time.xxxx;
vec4 WoPI = W / PI;
@ -66,39 +79,35 @@ void main()
vec4 IAccum = zero;
vec4 QAccum = zero;
for (int index = 0; index < 64; index = index + 4)
vec4 Cy = v_texcoord0.yyyy;
vec4 VPosition = Cy;
for (int i = 0; i < 64; i = i + 4)
{
float n = float(index);
vec4 n4 = vec4(n, n, n, n) + vec4(0.0, 1.0, 2.0, 3.0);
vec4 n = vec4(i, i, i, i) - vec4(32.0, 32.0, 32.0, 32.0);
vec4 n4 = n + vec4(0.0, 1.0, 2.0, 3.0);
vec4 Cx = v_texcoord0.xxxx + u_source_dims.xxxx * (n4 * quarter);
vec4 Cx = v_texcoord0.xxxx + (n4 * quarter) / u_source_dims.xxxx;
vec4 HPosition = Cx;
// theory: What if we put white in the input of the NTSC decode shader?
vec4 C = texture2D(s_tex, vec2(Cx.x, v_texcoord0.y));
vec4 C = texture2D(s_tex, vec2(Cx.x, Cy.x));
vec4 T = Cx + HOffset + v_texcoord0.yyyy * VScale;
vec4 T = HPosition + HOffset + VPosition * VScale;
vec4 WT = W * T + u_o_value.xxxx;
vec4 SincKernel = vec4(0.54, 0.54, 0.54, 0.54) + vec4(0.46, 0.46, 0.46, 0.46) * cos((PI2 / 1.0) * n4);
vec4 SincKernel = vec4(0.54, 0.54, 0.54, 0.54) + vec4(0.46, 0.46, 0.46, 0.46) * cos(PI2Length * n4);
vec4 SincYIn1 = Fc_y1 * PI2 * n4;
vec4 SincYIn2 = Fc_y2 * PI2 * n4;
vec4 SincYIn3 = Fc_y3 * PI2 * n4;
vec4 SincIIn = Fc_i * PI2 * n4;
vec4 SincQIn = Fc_q * PI2 * n4;
SincYIn1 = SincYIn1 == zero ? one : SincYIn1;
SincYIn2 = SincYIn2 == zero ? one : SincYIn2;
SincYIn3 = SincYIn3 == zero ? one : SincYIn3;
SincIIn = SincIIn == zero ? one : SincIIn;
SincQIn = SincQIn == zero ? one : SincQIn;
vec4 SincYIn1 = Fc_y1_pi2 * n4;
vec4 SincYIn2 = Fc_y2_pi2 * n4;
vec4 SincYIn3 = Fc_y3_pi2 * n4;
vec4 SincIIn = Fc_i_pi2 * n4;
vec4 SincQIn = Fc_q_pi2 * n4;
vec4 SincY1 = SincYIn1 != zero ? sin(SincYIn1) / SincYIn1 : one;
vec4 SincY2 = SincYIn2 != zero ? sin(SincYIn2) / SincYIn2 : one;
vec4 SincY3 = SincYIn3 != zero ? sin(SincYIn3) / SincYIn3 : one;
vec4 IdealY = (Fc_y1 * two * SincY1 - Fc_y2 * two * SincY2) + Fc_y3 * two * SincY3;
vec4 IdealY = (Fc_y1_2 * SincY1 - Fc_y2_2 * SincY2) + Fc_y3_2 * SincY3;
vec4 IdealI = Fc_i_2 * (SincIIn != zero ? sin(SincIIn) / SincIIn : one);
vec4 IdealQ = Fc_q_2 * (SincQIn != zero ? sin(SincQIn) / SincQIn : one);

View File

@ -65,7 +65,7 @@ void main()
float HOffset = (u_a_value.x + u_jitter_amount.x * u_jitter_offset.x) / WoPI;
float VScale = (u_b_value.x * u_source_dims.y) / WoPI;
vec4 T = Cx + vec4(HOffset, HOffset, HOffset, HOffset) + Cy * vec4(VScale, VScale, VScale, VScale);
vec4 T = HPosition + vec4(HOffset, HOffset, HOffset, HOffset) + VPosition * vec4(VScale, VScale, VScale, VScale);
vec4 TW = T * W;
gl_FragColor = Y + I * cos(TW) + Q * sin(TW);