From d516871e6fcbde11863b927de75a042e8b8ce3e9 Mon Sep 17 00:00:00 2001 From: ImJezze Date: Mon, 25 Jan 2016 22:02:24 +0100 Subject: NTSC Refactoring and Options - merged YIQ encode and decode pass into one NTSC pass - added options for most NTSC settings - reduced sample count to 64 - changed default O value to 0 - fit NTSC signal jitter between a reasonable limit of 0 and 1 - fit A and B value between a reasonable limit of -1 and 1 - fit scanline jitter between a reasonable limit of 0 and 1 - added hum bar simulation based on [MooglyGuy's] GLSL port of the mame shader pipeline - added monochrome-chessboard.png - added slot-mask-aligned.png (to simulate a TFT LCD) --- artwork/monochrome-chessboard.png | Bin 0 -> 23358 bytes artwork/monochrome-matrix.png | Bin 31397 -> 33194 bytes artwork/slot-mask-aligned.png | Bin 0 -> 26638 bytes docs/hlsl.txt | 28 ++-- hlsl/artwork_support/post.fx | 30 ++-- hlsl/ntsc.fx | 251 +++++++++++++++++++++++++++++++++ hlsl/post.fx | 30 +++- hlsl/yiq_decode.fx | 215 ---------------------------- hlsl/yiq_encode.fx | 151 -------------------- src/osd/modules/render/d3d/d3dhlsl.cpp | 218 +++++++++++++++++++--------- src/osd/modules/render/d3d/d3dhlsl.h | 7 +- src/osd/windows/winmain.cpp | 10 +- src/osd/windows/winmain.h | 8 +- 13 files changed, 482 insertions(+), 466 deletions(-) create mode 100644 artwork/monochrome-chessboard.png create mode 100644 artwork/slot-mask-aligned.png create mode 100644 hlsl/ntsc.fx delete mode 100644 hlsl/yiq_decode.fx delete mode 100644 hlsl/yiq_encode.fx diff --git a/artwork/monochrome-chessboard.png b/artwork/monochrome-chessboard.png new file mode 100644 index 00000000000..b10019847bf Binary files /dev/null and b/artwork/monochrome-chessboard.png differ diff --git a/artwork/monochrome-matrix.png b/artwork/monochrome-matrix.png index c44d063c397..c1180363087 100644 Binary files a/artwork/monochrome-matrix.png and b/artwork/monochrome-matrix.png differ diff --git a/artwork/slot-mask-aligned.png b/artwork/slot-mask-aligned.png new file mode 100644 index 00000000000..764c5fcb5be Binary files /dev/null and b/artwork/slot-mask-aligned.png differ diff --git a/docs/hlsl.txt b/docs/hlsl.txt index 5bde3f85ebb..d42f608c5c5 100644 --- a/docs/hlsl.txt +++ b/docs/hlsl.txt @@ -38,15 +38,16 @@ scanline_size 0.0 to 4.0 The overall height of each scanline. scanline_height [height] Individual height scaling value for scanlines. scanline_bright_scale 0.0 to 2.0 The overall brightness multiplier for each scanline. scanline_bright_offset 0.0 to 1.0 The overall brightness additive value for each scanline. -scanline_jitter 0.0 to 2.0 The relative scanline movement per field. +scanline_jitter 0.0 to 1.0 The relative scanline movement per field. +hum_bar_alpha 0.0 to 1.0 The maximum darkness of the hum bar gradient. defocus [xval,yval] This defines the overall defocus radius for the three - post-converged beams. Values allowed range from 0.0 to - 32.0. + post-converged beams. Values allowed range from 0.0 to + 10.0. converge_x [r,g,b] Convergence in screen-relative X direction. converge_y [r,g,b] Convergence in screen-relative Y direction. radial_converge_x [r,g,b] Radial convergence in screen-relative X direction. radial_converge_y [r,g,b] Radial convergence in screen-relative Y direction. - Allowed values for convergence: -150 to 150 for each color. + Allowed values for convergence: -10.0 to 10.0 for each color. red_ratio [r,g,b] These parameters define a 3x3 matrix which is multiplied grn_ratio [r,g,b] by the incoming RGB signal. This can be used for any blu_ratio [r,g,b] standard matrix convolution, including H/S/V or simply @@ -78,15 +79,16 @@ NTSC Processing Parameters -------------------------- Name Default Values Description -yiq_cc 3.59754545 Color Carrier frequency for NTSC signal processing. -yiq_a 0.5 A value for NTSC signal processing. -yiq_b 0.5 B value for NTSC signal processing. -yiq_o 0.0 Outgoing Color Carrier phase offset for NTSC signal processing. -yiq_p 1.0 Incoming Pixel Clock scaling value for NTSC signal processing. -yiq_n 1.0 Y filter notch width for NTSC signal processing. -yiq_y 6.0 Y filter cutoff frequency for NTSC signal processing. -yiq_i 1.2 I filter cutoff frequency for NTSC signal processing. -yiq_q 0.6 Q filter cutoff frequency for NTSC signal processing. +yiq_jitter 0.0 Jitter for the NTSC signal processing. (0.0 to 1.0) +yiq_cc 3.57954545 Color Carrier frequency for NTSC signal processing. (0.0 to 6.0) +yiq_a 0.5 A value for NTSC signal processing. (-1.0 to 1.0) +yiq_b 0.5 B value for NTSC signal processing. (-1.0 to 1.0) +yiq_o 0.0 Outgoing Color Carrier phase offset for NTSC signal processing. (-3.0 to 3.0) +yiq_p 1.0 Incoming Pixel Clock scaling value for NTSC signal processing. (-3.0 to 3.0) +yiq_n 1.0 Y filter notch width for NTSC signal processing. (0.0 to 6.0) +yiq_y 6.0 Y filter cutoff frequency for NTSC signal processing. (0.0 to 6.0) +yiq_i 1.2 I filter cutoff frequency for NTSC signal processing. (0.0 to 6.0) +yiq_q 0.6 Q filter cutoff frequency for NTSC signal processing. (0.0 to 6.0) yiq_scan_time 52.6 Horizontal scanline duration for NTSC signal processing. (usec) yiq_phase_count 2 Phase Count value for NTSC signal processing. (3 for NES, else 2) diff --git a/hlsl/artwork_support/post.fx b/hlsl/artwork_support/post.fx index 8da6dabf1ab..f0c883fa69e 100644 --- a/hlsl/artwork_support/post.fx +++ b/hlsl/artwork_support/post.fx @@ -151,6 +151,11 @@ VS_OUTPUT vs_main(VS_INPUT Input) // Scanline, Shadowmask & Distortion Pixel Shader //----------------------------------------------------------------------------- +uniform float HumBarHertzRate = 60.0f / 59.94f - 1.0f; // difference between the 59.94 Hz field rate and 60 Hz line frequency (NTSC) +uniform float HumBarAlpha = 0.0f; + +uniform float TimeMilliseconds = 0.0f; + uniform float2 ScreenScale = float2(1.0f, 1.0f); uniform float2 ScreenOffset = float2(0.0f, 0.0f); @@ -396,7 +401,7 @@ float4 ps_main(PS_INPUT Input) : COLOR } // Mask Simulation (may not affect bloom) - if (!PrepareBloom) + if (!PrepareBloom && ShadowAlpha > 0.0f) { float2 shadowDims = ShadowDims; shadowDims = SwapXY @@ -455,15 +460,24 @@ float4 ps_main(PS_INPUT Input) : COLOR // Scanline Simulation (may not affect bloom) if (!PrepareBloom) { - // Scanline Simulation (disabled for vector) - if (!PrepareVector) + // Scanline Simulation (may not affect vector screen) + if (!PrepareVector && ScanlineAlpha > 0.0f) { - float InnerSine = BaseCoord.y * ScanlineScale * SourceDims.y; - float ScanJitter = ScanlineOffset * SourceDims.y; - float ScanBrightMod = sin(InnerSine * PI + ScanJitter); - float3 ScanColor = lerp(1.0f, (pow(ScanBrightMod * ScanBrightMod, ScanlineHeight) * ScanlineBrightScale + 1.0f + ScanlineBrightOffset) * 0.5f, ScanlineAlpha); + float ScanCoord = BaseCoord.y * SourceDims.y * ScanlineScale * PI; + float ScanCoordJitter = ScanlineOffset * PHI; + float ScanSine = sin(ScanCoord + ScanCoordJitter); + float ScanSineScaled = pow(ScanSine * ScanSine, ScanlineHeight); + float ScanBrightness = ScanSineScaled * ScanlineBrightScale + 1.0f + ScanlineBrightOffset; - BaseColor.rgb *= ScanColor; + BaseColor.rgb *= lerp(1.0f, ScanBrightness * 0.5f, ScanlineAlpha); + } + + // Hum Bar Simulation (may not affect vector screen) + if (!PrepareVector && HumBarAlpha > 0.0f) + { + float HumTimeStep = frac(TimeMilliseconds * HumBarHertzRate); + float HumBrightness = 1.0 - frac(BaseCoord.y / SourceRect.y + HumTimeStep) * HumBarAlpha; + BaseColor.rgb *= HumBrightness; } } diff --git a/hlsl/ntsc.fx b/hlsl/ntsc.fx new file mode 100644 index 00000000000..ed07e37a4cc --- /dev/null +++ b/hlsl/ntsc.fx @@ -0,0 +1,251 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz,ImJezze +//----------------------------------------------------------------------------- +// NTSC Effect +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Sampler Definitions +//----------------------------------------------------------------------------- + +texture Diffuse; + +sampler DiffuseSampler = sampler_state +{ + Texture = ; + MipFilter = LINEAR; + MinFilter = LINEAR; + MagFilter = LINEAR; + AddressU = CLAMP; + AddressV = CLAMP; + AddressW = CLAMP; +}; + +//----------------------------------------------------------------------------- +// Vertex Definitions +//----------------------------------------------------------------------------- + +struct VS_OUTPUT +{ + float4 Position : POSITION; + float4 TexCoord : TEXCOORD0; +}; + +struct VS_INPUT +{ + float4 Position : POSITION; + float4 Color : COLOR0; + float2 TexCoord : TEXCOORD0; +}; + +struct PS_INPUT +{ + float2 TexCoord : TEXCOORD0; +}; + +//----------------------------------------------------------------------------- +// YIQ Decode Vertex Shader +//----------------------------------------------------------------------------- + +uniform float2 ScreenDims; +uniform float2 SourceDims; +uniform float2 SourceRect; + +VS_OUTPUT vs_main(VS_INPUT Input) +{ + VS_OUTPUT Output = (VS_OUTPUT)0; + + Output.Position = float4(Input.Position.xyz, 1.0f); + Output.Position.xy /= ScreenDims; + Output.Position.y = 1.0f - Output.Position.y; // flip y + Output.Position.xy -= 0.5f; // center + Output.Position.xy *= 2.0f; // zoom + + Output.TexCoord.xy = Input.TexCoord; + Output.TexCoord.xy += 0.5f / SourceDims; // half texel offset correction (DX9) + + return Output; +} + +//----------------------------------------------------------------------------- +// NTSC Pixel Shader +//----------------------------------------------------------------------------- + +uniform float AValue = 0.5f; +uniform float BValue = 0.5f; +uniform float CCValue = 3.5795454f; +uniform float OValue = 0.0f; +uniform float PValue = 1.0f; +uniform float ScanTime = 52.6f; + +uniform float NotchHalfWidth = 1.0f; +uniform float YFreqResponse = 6.0f; +uniform float IFreqResponse = 1.2f; +uniform float QFreqResponse = 0.6f; + +uniform float SignalOffset = 0.0f; + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +static const float PI = 3.1415927f; +static const float PI2 = PI * 2.0f; + +static const float4 YDot = float4(0.299f, 0.587f, 0.114f, 0.0f); +static const float4 IDot = float4(0.595716f, -0.274453f, -0.321263f, 0.0f); +static const float4 QDot = float4(0.211456f, -0.522591f, 0.311135f, 0.0f); + +static const float3 RDot = float3(1.0f, 0.956f, 0.621f); +static const float3 GDot = float3(1.0f, -0.272f, -0.647f); +static const float3 BDot = float3(1.0f, -1.106f, 1.703f); + +static const float4 OffsetX = float4(0.0f, 0.25f, 0.50f, 0.75f); +static const float4 NotchOffset = float4(0.0f, 1.0f, 2.0f, 3.0f); + +static const int SampleCount = 64; +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 C0 = TexCoord + PValueSourceTexel * OffsetX.x; + float2 C1 = TexCoord + PValueSourceTexel * OffsetX.y; + float2 C2 = TexCoord + PValueSourceTexel * OffsetX.z; + float2 C3 = TexCoord + PValueSourceTexel * OffsetX.w; + float4 Cx = float4(C0.x, C1.x, C2.x, C3.x); + float4 Cy = float4(C0.y, C1.y, C2.y, C3.y); + float4 Texel0 = tex2D(DiffuseSampler, C0); + float4 Texel1 = tex2D(DiffuseSampler, C1); + float4 Texel2 = tex2D(DiffuseSampler, C2); + float4 Texel3 = tex2D(DiffuseSampler, C3); + + float4 HPosition = Cx / SourceRect.x; + float4 VPosition = Cy / SourceRect.y; + + 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)); + float4 Q = float4(dot(Texel0, QDot), dot(Texel1, QDot), dot(Texel2, QDot), dot(Texel3, QDot)); + + float4 W = PI2 * CCValue * ScanTime; + + float4 T = HPosition + + (AValue / 360.0f * SourceRes.y) * VPosition + + (BValue / 360.0f) + + (SignalOffset / 360.0f); + float4 TW = T * W; + + float4 CompositeYIQ = Y + I * cos(TW) + Q * sin(TW); + + return CompositeYIQ; +} + +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 Fc_y1 = (CCValue - NotchHalfWidth) * TimePerSample; + float Fc_y2 = (CCValue + NotchHalfWidth) * TimePerSample; + float Fc_y3 = YFreqResponse * TimePerSample; + float Fc_i = IFreqResponse * TimePerSample; + float Fc_q = QFreqResponse * TimePerSample; + float Fc_i_2 = Fc_i * 2.0f; + float Fc_q_2 = Fc_q * 2.0f; + float Fc_y1_2 = Fc_y1 * 2.0f; + float Fc_y2_2 = Fc_y2 * 2.0f; + float Fc_y3_2 = Fc_y3 * 2.0f; + float Fc_i_pi2 = Fc_i * PI2; + float Fc_q_pi2 = Fc_q * PI2; + float Fc_y1_pi2 = Fc_y1 * PI2; + float Fc_y2_pi2 = Fc_y2 * PI2; + float Fc_y3_pi2 = Fc_y3 * PI2; + float PI2Length = PI2 / SampleCount; + + float W = PI2 * CCValue * ScanTime; + + float4 YAccum = 0.0f; + float4 IAccum = 0.0f; + float4 QAccum = 0.0f; + + float4 Cy = Input.TexCoord.y; + float4 VPosition = Cy / SourceRect.y; + + 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 C = GetCompositeYIQ(float2(Cx.r, Cy.r)); + + float4 T = HPosition + + (AValue / 360.0f * SourceRes.y) * VPosition + + (BValue / 360.0f) + + (SignalOffset / 360.0f); + float4 WT = W * T + + OValue; + + float4 SincKernel = 0.54f + 0.46f * cos(PI2Length * n4); + + float4 SincYIn1 = Fc_y1_pi2 * n4; + float4 SincYIn2 = Fc_y2_pi2 * n4; + float4 SincYIn3 = Fc_y3_pi2 * n4; + float4 SincIIn = Fc_i_pi2 * n4; + float4 SincQIn = Fc_q_pi2 * n4; + + float4 SincY1 = SincYIn1 != 0.0f ? sin(SincYIn1) / SincYIn1 : 1.0f; + float4 SincY2 = SincYIn2 != 0.0f ? sin(SincYIn2) / SincYIn2 : 1.0f; + float4 SincY3 = SincYIn3 != 0.0f ? sin(SincYIn3) / SincYIn3 : 1.0f; + + float4 IdealY = (Fc_y1_2 * SincY1 - Fc_y2_2 * SincY2) + Fc_y3_2 * SincY3; + float4 IdealI = Fc_i_2 * (SincIIn != 0.0f ? sin(SincIIn) / SincIIn : 1.0f); + float4 IdealQ = Fc_q_2 * (SincQIn != 0.0f ? sin(SincQIn) / SincQIn : 1.0f); + + float4 FilterY = SincKernel * IdealY; + float4 FilterI = SincKernel * IdealI; + float4 FilterQ = SincKernel * IdealQ; + + YAccum = YAccum + C * FilterY; + IAccum = IAccum + C * cos(WT) * FilterI; + QAccum = QAccum + C * sin(WT) * FilterQ; + } + + float3 YIQ = float3( + (YAccum.r + YAccum.g + YAccum.b + YAccum.a), + (IAccum.r + IAccum.g + IAccum.b + IAccum.a) * 2.0f, + (QAccum.r + QAccum.g + QAccum.b + QAccum.a) * 2.0f); + + float3 RGB = float3( + dot(YIQ, RDot), + dot(YIQ, GDot), + dot(YIQ, BDot)); + + return float4(RGB, BaseTexel.a); +} + +//----------------------------------------------------------------------------- +// NTSC Technique +//----------------------------------------------------------------------------- + +technique DefaultTechnique +{ + pass Pass0 + { + Lighting = FALSE; + + VertexShader = compile vs_3_0 vs_main(); + PixelShader = compile ps_3_0 ps_main(); + } +} diff --git a/hlsl/post.fx b/hlsl/post.fx index 4415298a2f8..deec349e2fc 100644 --- a/hlsl/post.fx +++ b/hlsl/post.fx @@ -65,6 +65,7 @@ struct PS_INPUT //----------------------------------------------------------------------------- static const float PI = 3.1415927f; +static const float PHI = 1.618034f; //----------------------------------------------------------------------------- // Scanline & Shadowmask Vertex Shader @@ -118,6 +119,11 @@ VS_OUTPUT vs_main(VS_INPUT Input) // Scanline & Shadowmask Pixel Shader //----------------------------------------------------------------------------- +uniform float HumBarHertzRate = 60.0f / 59.94f - 1.0f; // difference between the 59.94 Hz field rate and 60 Hz line frequency (NTSC) +uniform float HumBarAlpha = 0.0f; + +uniform float TimeMilliseconds = 0.0f; + uniform float2 ScreenScale = float2(1.0f, 1.0f); uniform float2 ScreenOffset = float2(0.0f, 0.0f); @@ -159,6 +165,7 @@ float4 ps_main(PS_INPUT Input) : COLOR { float2 ScreenTexelDims = 1.0f / ScreenDims; float2 SourceTexelDims = 1.0f / SourceDims; + float2 SourceRes = SourceDims * SourceRect; float2 HalfSourceRect = SourceRect * 0.5f; @@ -175,7 +182,7 @@ float4 ps_main(PS_INPUT Input) : COLOR } // Mask Simulation (may not affect bloom) - if (!PrepareBloom) + if (!PrepareBloom && ShadowAlpha > 0.0f) { float2 shadowDims = ShadowDims; shadowDims = SwapXY @@ -235,14 +242,23 @@ float4 ps_main(PS_INPUT Input) : COLOR if (!PrepareBloom) { // Scanline Simulation (may not affect vector screen) - if (!PrepareVector) + if (!PrepareVector && ScanlineAlpha > 0.0f) { - float InnerSine = BaseCoord.y * ScanlineScale * SourceDims.y; - float ScanJitter = ScanlineOffset * SourceDims.y; - float ScanBrightMod = sin(InnerSine * PI + ScanJitter); - float3 ScanColor = lerp(1.0f, (pow(ScanBrightMod * ScanBrightMod, ScanlineHeight) * ScanlineBrightScale + 1.0f + ScanlineBrightOffset) * 0.5f, ScanlineAlpha); + float ScanCoord = BaseCoord.y * SourceDims.y * ScanlineScale * PI; + float ScanCoordJitter = ScanlineOffset * PHI; + float ScanSine = sin(ScanCoord + ScanCoordJitter); + float ScanSineScaled = pow(ScanSine * ScanSine, ScanlineHeight); + float ScanBrightness = ScanSineScaled * ScanlineBrightScale + 1.0f + ScanlineBrightOffset; - BaseColor.rgb *= ScanColor; + BaseColor.rgb *= lerp(1.0f, ScanBrightness * 0.5f, ScanlineAlpha); + } + + // Hum Bar Simulation (may not affect vector screen) + if (!PrepareVector && HumBarAlpha > 0.0f) + { + float HumTimeStep = frac(TimeMilliseconds * HumBarHertzRate); + float HumBrightness = 1.0 - frac(BaseCoord.y / SourceRect.y + HumTimeStep) * HumBarAlpha; + BaseColor.rgb *= HumBrightness; } } diff --git a/hlsl/yiq_decode.fx b/hlsl/yiq_decode.fx deleted file mode 100644 index 288d00b2312..00000000000 --- a/hlsl/yiq_decode.fx +++ /dev/null @@ -1,215 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz,ImJezze -//----------------------------------------------------------------------------- -// YIQ Decode Effect -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Sampler Definitions -//----------------------------------------------------------------------------- - -texture Composite; - -sampler CompositeSampler = sampler_state -{ - Texture = ; - MipFilter = POINT; - MinFilter = POINT; - MagFilter = POINT; - AddressU = CLAMP; - AddressV = CLAMP; - AddressW = CLAMP; -}; - -texture Diffuse; - -sampler DiffuseSampler = sampler_state -{ - Texture = ; - MipFilter = LINEAR; - MinFilter = LINEAR; - MagFilter = LINEAR; - AddressU = CLAMP; - AddressV = CLAMP; - AddressW = CLAMP; -}; - -//----------------------------------------------------------------------------- -// Vertex Definitions -//----------------------------------------------------------------------------- - -struct VS_OUTPUT -{ - float4 Position : POSITION; - float4 TexCoord : TEXCOORD0; -}; - -struct VS_INPUT -{ - float4 Position : POSITION; - float4 Color : COLOR0; - float2 TexCoord : TEXCOORD0; -}; - -struct PS_INPUT -{ - float2 TexCoord : TEXCOORD0; -}; - -//----------------------------------------------------------------------------- -// YIQ Decode Vertex Shader -//----------------------------------------------------------------------------- - -uniform float2 ScreenDims; -uniform float2 SourceDims; -uniform float2 SourceRect; - -VS_OUTPUT vs_main(VS_INPUT Input) -{ - VS_OUTPUT Output = (VS_OUTPUT)0; - - Output.Position = float4(Input.Position.xyz, 1.0f); - Output.Position.xy /= ScreenDims; - Output.Position.y = 1.0f - Output.Position.y; // flip y - Output.Position.xy -= 0.5f; // center - Output.Position.xy *= 2.0f; // zoom - - Output.TexCoord.xy = Input.TexCoord; - Output.TexCoord.xy += 0.5f / SourceDims; // half texel offset correction (DX9) - - return Output; -} - -//----------------------------------------------------------------------------- -// YIQ Decode Pixel Shader -//----------------------------------------------------------------------------- - -uniform float AValue = 0.5f; -uniform float BValue = 0.5f; -uniform float CCValue = 3.5975454f; -uniform float OValue = 0.0f; -uniform float PValue = 1.0f; // unused - -uniform float ScanTime = 52.6f; -uniform float FrameOffset = 0.0f; - -uniform float NotchHalfWidth = 1.0f; -uniform float YFreqResponse = 6.0f; -uniform float IFreqResponse = 1.2f; -uniform float QFreqResponse = 0.6f; - -//----------------------------------------------------------------------------- -// Constants -//----------------------------------------------------------------------------- - -static const float4 NotchOffset = float4(0.0f, 1.0f, 2.0f, 3.0f); - -static const float PI = 3.1415927f; -static const float PI2 = 6.2831855f; - -static const float MaxC = 2.1183f; -static const float MinC = -1.1183f; -static const float CRange = 3.2366f; - -float4 ps_main(PS_INPUT Input) : COLOR -{ - float4 BaseTexel = tex2D(DiffuseSampler, Input.TexCoord.xy); - - float2 InvDims = 1.0f / SourceDims; - - // YIQ convolution: N coefficients each - float4 YAccum = 0.0f; - float4 IAccum = 0.0f; - float4 QAccum = 0.0f; - - float BValueFrameOffset = BValue * FrameOffset; - - float FrameWidthx4 = SourceDims.x * SourceRect.x * 4.0f; - float TimePerSample = ScanTime / FrameWidthx4; - - float Fc_y1 = (CCValue - NotchHalfWidth) * TimePerSample; - float Fc_y2 = (CCValue + NotchHalfWidth) * TimePerSample; - float Fc_y3 = YFreqResponse * TimePerSample; - float Fc_i = IFreqResponse * TimePerSample; - float Fc_q = QFreqResponse * TimePerSample; - float Fc_i_2 = Fc_i * 2.0f; - float Fc_q_2 = Fc_q * 2.0f; - float Fc_y1_2 = Fc_y1 * 2.0f; - float Fc_y2_2 = Fc_y2 * 2.0f; - float Fc_y3_2 = Fc_y3 * 2.0f; - float Fc_i_pi2 = Fc_i * PI2; - float Fc_q_pi2 = Fc_q * PI2; - float Fc_y1_pi2 = Fc_y1 * PI2; - float Fc_y2_pi2 = Fc_y2 * PI2; - float Fc_y3_pi2 = Fc_y3 * PI2; - float PI2Length = PI2 / 82.0f; - - float W = PI2 * CCValue * ScanTime; - - float4 Cy = Input.TexCoord.y; - float4 VPosition = Cy * (SourceDims.y * SourceRect.y) * 2.0f; - - for(float n = -41.0f; n < 42.0f; n += 4.0f) - { - float4 n4 = n + NotchOffset; - - float4 Cx = Input.TexCoord.x + InvDims.x * n4 * 0.25f; - float4 HPosition = (Cx / SourceRect.x); - - float4 C = tex2D(CompositeSampler, float2(Cx.r, Cy.r)) * CRange + MinC; - - float4 T = HPosition + AValue * VPosition + BValueFrameOffset; - float4 WT = W * T + OValue; - - float4 SincKernel = 0.54f + 0.46f * cos(PI2Length * n4); - - float4 SincYIn1 = Fc_y1_pi2 * n4; - float4 SincYIn2 = Fc_y2_pi2 * n4; - float4 SincYIn3 = Fc_y3_pi2 * n4; - float4 SincIIn = Fc_i_pi2 * n4; - float4 SincQIn = Fc_q_pi2 * n4; - - float4 SincY1 = SincYIn1 != 0.0f ? sin(SincYIn1) / SincYIn1 : 1.0f; - float4 SincY2 = SincYIn2 != 0.0f ? sin(SincYIn2) / SincYIn2 : 1.0f; - float4 SincY3 = SincYIn3 != 0.0f ? sin(SincYIn3) / SincYIn3 : 1.0f; - - float4 IdealY = (Fc_y1_2 * SincY1 - Fc_y2_2 * SincY2) + Fc_y3_2 * SincY3; - float4 IdealI = Fc_i_2 * (SincIIn != 0.0f ? sin(SincIIn) / SincIIn : 1.0f); - float4 IdealQ = Fc_q_2 * (SincQIn != 0.0f ? sin(SincQIn) / SincQIn : 1.0f); - - float4 FilterY = SincKernel * IdealY; - float4 FilterI = SincKernel * IdealI; - float4 FilterQ = SincKernel * IdealQ; - - YAccum = YAccum + C * FilterY; - IAccum = IAccum + C * cos(WT) * FilterI; - QAccum = QAccum + C * sin(WT) * FilterQ; - } - - float Y = YAccum.r + YAccum.g + YAccum.b + YAccum.a; - float I = (IAccum.r + IAccum.g + IAccum.b + IAccum.a) * 2.0f; - float Q = (QAccum.r + QAccum.g + QAccum.b + QAccum.a) * 2.0f; - - float3 YIQ = float3(Y, I, Q); - - float3 Decode = float3( - dot(YIQ, float3(1.0f, 0.956f, 0.621f)), - dot(YIQ, float3(1.0f, -0.272f, -0.647f)), - dot(YIQ, float3(1.0f, -1.106f, 1.703f))); - return float4(Decode, BaseTexel.a); -} - -//----------------------------------------------------------------------------- -// YIQ Decode Technique -//----------------------------------------------------------------------------- - -technique DefaultTechnique -{ - pass Pass0 - { - Lighting = FALSE; - - VertexShader = compile vs_3_0 vs_main(); - PixelShader = compile ps_3_0 ps_main(); - } -} diff --git a/hlsl/yiq_encode.fx b/hlsl/yiq_encode.fx deleted file mode 100644 index c0db1cf531d..00000000000 --- a/hlsl/yiq_encode.fx +++ /dev/null @@ -1,151 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz,ImJezze -//----------------------------------------------------------------------------- -// YIQ Encode Effect -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Sampler Definitions -//----------------------------------------------------------------------------- - -texture Diffuse; - -sampler DiffuseSampler = sampler_state -{ - Texture = ; - MipFilter = LINEAR; - MinFilter = LINEAR; - MagFilter = LINEAR; - AddressU = CLAMP; - AddressV = CLAMP; - AddressW = CLAMP; -}; - -//----------------------------------------------------------------------------- -// Vertex Definitions -//----------------------------------------------------------------------------- - -struct VS_OUTPUT -{ - float4 Position : POSITION; - float4 Color : COLOR0; - float2 TexCoord : TEXCOORD0; -}; - -struct VS_INPUT -{ - float4 Position : POSITION; - float4 Color : COLOR0; - float2 TexCoord : TEXCOORD0; -}; - -struct PS_INPUT -{ - float4 Color : COLOR0; - float2 TexCoord : TEXCOORD0; -}; - -//----------------------------------------------------------------------------- -// YIQ Encode Vertex Shader -//----------------------------------------------------------------------------- - -uniform float2 ScreenDims; -uniform float2 SourceDims; -uniform float2 SourceRect; - -VS_OUTPUT vs_main(VS_INPUT Input) -{ - VS_OUTPUT Output = (VS_OUTPUT)0; - - Output.Position = float4(Input.Position.xyz, 1.0f); - Output.Position.xy /= ScreenDims; - Output.Position.y = 1.0f - Output.Position.y; // flip y - Output.Position.xy -= 0.5f; // center - Output.Position.xy *= 2.0f; // zoom - - Output.TexCoord = Input.TexCoord; - Output.TexCoord += 0.5f / SourceDims; // half texel offset correction (DX9) - - Output.Color = Input.Color; - - return Output; -} - -//----------------------------------------------------------------------------- -// YIQ Encode Pixel Shader -//----------------------------------------------------------------------------- - -uniform float AValue = 0.5f; -uniform float BValue = 0.5f; -uniform float CCValue = 3.5975454f; -uniform float OValue = 0.0f; -uniform float PValue = 1.0f; - -uniform float ScanTime = 52.6f; -uniform float FrameOffset = 0.0f; - -uniform float MaxC = 2.1183f; -uniform float MinC = -1.1183f; -uniform float CRange = 3.2366f; - -//----------------------------------------------------------------------------- -// Constants -//----------------------------------------------------------------------------- - -static const float4 YDot = float4(0.299f, 0.587f, 0.114f, 0.0f); -static const float4 IDot = float4(0.595716f, -0.274453f, -0.321263f, 0.0f); -static const float4 QDot = float4(0.211456f, -0.522591f, 0.311135f, 0.0f); -static const float4 OffsetX = float4(0.0f, 0.25f, 0.50f, 0.75f); - -static const float PI = 3.1415927f; -static const float PI2 = 6.2831855f; - -float4 ps_main(PS_INPUT Input) : COLOR -{ - float2 InvDims = 1.0f / SourceDims; - - float2 InvPValue = float2(PValue, 0.0f) * InvDims; - - float2 C0 = Input.TexCoord + InvPValue * OffsetX.x; - float2 C1 = Input.TexCoord + InvPValue * OffsetX.y; - float2 C2 = Input.TexCoord + InvPValue * OffsetX.z; - float2 C3 = Input.TexCoord + InvPValue * OffsetX.w; - float4 Cx = float4(C0.x, C1.x, C2.x, C3.x); - float4 Cy = float4(C0.y, C1.y, C2.y, C3.y); - float4 Texel0 = tex2D(DiffuseSampler, C0); - float4 Texel1 = tex2D(DiffuseSampler, C1); - float4 Texel2 = tex2D(DiffuseSampler, C2); - float4 Texel3 = tex2D(DiffuseSampler, C3); - - 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)); - float4 Q = float4(dot(Texel0, QDot), dot(Texel1, QDot), dot(Texel2, QDot), dot(Texel3, QDot)); - - float BValueFrameOffset = BValue * FrameOffset; - - float4 HPosition = Cx / SourceRect.x; - float4 VPosition = Cy * (SourceDims.y * SourceRect.y) * 2.0f; - - float4 W = PI2 * CCValue * ScanTime; - float4 T = HPosition + AValue * VPosition + BValueFrameOffset; - float4 TW = T * W + OValue; - - float4 Encoded = Y + I * cos(TW) + Q * sin(TW); - - return (Encoded - MinC) / CRange;; -} - -//----------------------------------------------------------------------------- -// YIQ Encode Technique -//----------------------------------------------------------------------------- - -technique DefaultTechnique -{ - pass Pass0 - { - Lighting = FALSE; - - VertexShader = compile vs_3_0 vs_main(); - PixelShader = compile ps_3_0 ps_main(); - } -} diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp index 0280dd31e68..8a60eaa5190 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.cpp +++ b/src/osd/modules/render/d3d/d3dhlsl.cpp @@ -76,7 +76,7 @@ shaders::shaders() : vecbuf_type(), vecbuf_index(0), vecbuf_count(0), avi_output_file(NULL), avi_frame(0), avi_copy_surface(NULL), avi_copy_texture(NULL), avi_final_target(NULL), avi_final_texture(NULL), black_surface(NULL), black_texture(NULL), render_snap(false), snap_rendered(false), snap_copy_target(NULL), snap_copy_texture(NULL), snap_target(NULL), snap_texture(NULL), snap_width(0), snap_height(0), lines_pending(false), backbuffer(NULL), curr_effect(NULL), default_effect(NULL), prescale_effect(NULL), post_effect(NULL), distortion_effect(NULL), - focus_effect(NULL), phosphor_effect(NULL), deconverge_effect(NULL), color_effect(NULL), yiq_encode_effect(NULL), yiq_decode_effect(NULL), bloom_effect(NULL), + focus_effect(NULL), phosphor_effect(NULL), deconverge_effect(NULL), color_effect(NULL), ntsc_effect(NULL), bloom_effect(NULL), downsample_effect(NULL), vector_effect(NULL), fsfx_vertices(NULL), curr_texture(NULL), curr_render_target(NULL), curr_poly(NULL) { master_enable = false; @@ -632,7 +632,7 @@ void shaders::set_texture(texture_info *texture) default_effect->set_texture("Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); if (options->yiq_enable) { - yiq_encode_effect->set_texture("Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); + ntsc_effect->set_texture("Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); } else { @@ -706,7 +706,8 @@ void shaders::init(base *d3dintf, running_machine *machine, d3d::renderer *rende options->scanline_height = winoptions.screen_scanline_height(); options->scanline_bright_scale = winoptions.screen_scanline_bright_scale(); options->scanline_bright_offset = winoptions.screen_scanline_bright_offset(); - options->scanline_offset = winoptions.screen_scanline_offset(); + options->scanline_jitter = winoptions.screen_scanline_jitter(); + options->hum_bar_alpha = winoptions.screen_hum_bar_alpha(); get_vector(winoptions.screen_defocus(), 2, options->defocus, TRUE); get_vector(winoptions.screen_converge_x(), 3, options->converge_x, TRUE); get_vector(winoptions.screen_converge_y(), 3, options->converge_y, TRUE); @@ -722,6 +723,7 @@ void shaders::init(base *d3dintf, running_machine *machine, d3d::renderer *rende get_vector(winoptions.screen_phosphor(), 3, options->phosphor, TRUE); options->saturation = winoptions.screen_saturation(); options->yiq_enable = winoptions.screen_yiq_enable(); + options->yiq_jitter = winoptions.screen_yiq_jitter(); options->yiq_cc = winoptions.screen_yiq_cc(); options->yiq_a = winoptions.screen_yiq_a(); options->yiq_b = winoptions.screen_yiq_b(); @@ -917,8 +919,7 @@ int shaders::create_resources(bool reset) focus_effect = new effect(this, d3d->get_device(), "focus.fx", fx_dir); deconverge_effect = new effect(this, d3d->get_device(), "deconverge.fx", fx_dir); color_effect = new effect(this, d3d->get_device(), "color.fx", fx_dir); - yiq_encode_effect = new effect(this, d3d->get_device(), "yiq_encode.fx", fx_dir); - yiq_decode_effect = new effect(this, d3d->get_device(), "yiq_decode.fx", fx_dir); + ntsc_effect = new effect(this, d3d->get_device(), "ntsc.fx", fx_dir); bloom_effect = new effect(this, d3d->get_device(), "bloom.fx", fx_dir); downsample_effect = new effect(this, d3d->get_device(), "downsample.fx", fx_dir); vector_effect = new effect(this, d3d->get_device(), "vector.fx", fx_dir); @@ -931,8 +932,7 @@ int shaders::create_resources(bool reset) !focus_effect->is_valid() || !deconverge_effect->is_valid() || !color_effect->is_valid() || - !yiq_encode_effect->is_valid() || - !yiq_decode_effect->is_valid() || + !ntsc_effect->is_valid() || !bloom_effect->is_valid() || !downsample_effect->is_valid() || !vector_effect->is_valid()) @@ -940,7 +940,7 @@ int shaders::create_resources(bool reset) return 1; } - effect *effects[14] = { + effect *effects[13] = { default_effect, post_effect, distortion_effect, @@ -949,15 +949,14 @@ int shaders::create_resources(bool reset) focus_effect, deconverge_effect, color_effect, - yiq_encode_effect, - yiq_decode_effect, + ntsc_effect, color_effect, bloom_effect, downsample_effect, vector_effect }; - for (int i = 0; i < 14; i++) + for (int i = 0; i < 13; i++) { effects[i]->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); effects[i]->add_uniform("SourceRect", uniform::UT_VEC2, uniform::CU_SOURCE_RECT); @@ -967,27 +966,16 @@ int shaders::create_resources(bool reset) effects[i]->add_uniform("SwapXY", uniform::UT_BOOL, uniform::CU_SWAP_XY); } - yiq_encode_effect->add_uniform("CCValue", uniform::UT_FLOAT, uniform::CU_NTSC_CCFREQ); - yiq_encode_effect->add_uniform("AValue", uniform::UT_FLOAT, uniform::CU_NTSC_A); - yiq_encode_effect->add_uniform("BValue", uniform::UT_FLOAT, uniform::CU_NTSC_B); - yiq_decode_effect->add_uniform("OValue", uniform::UT_FLOAT, uniform::CU_NTSC_O); - yiq_encode_effect->add_uniform("PValue", uniform::UT_FLOAT, uniform::CU_NTSC_P); - yiq_encode_effect->add_uniform("NotchHalfWidth", uniform::UT_FLOAT, uniform::CU_NTSC_NOTCH); - yiq_encode_effect->add_uniform("YFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_YFREQ); - yiq_encode_effect->add_uniform("IFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_IFREQ); - yiq_encode_effect->add_uniform("QFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_QFREQ); - yiq_encode_effect->add_uniform("ScanTime", uniform::UT_FLOAT, uniform::CU_NTSC_HTIME); - - yiq_decode_effect->add_uniform("CCValue", uniform::UT_FLOAT, uniform::CU_NTSC_CCFREQ); - yiq_decode_effect->add_uniform("AValue", uniform::UT_FLOAT, uniform::CU_NTSC_A); - yiq_decode_effect->add_uniform("BValue", uniform::UT_FLOAT, uniform::CU_NTSC_B); - yiq_decode_effect->add_uniform("OValue", uniform::UT_FLOAT, uniform::CU_NTSC_O); - yiq_decode_effect->add_uniform("PValue", uniform::UT_FLOAT, uniform::CU_NTSC_P); - yiq_decode_effect->add_uniform("NotchHalfWidth", uniform::UT_FLOAT, uniform::CU_NTSC_NOTCH); - yiq_decode_effect->add_uniform("YFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_YFREQ); - yiq_decode_effect->add_uniform("IFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_IFREQ); - yiq_decode_effect->add_uniform("QFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_QFREQ); - yiq_decode_effect->add_uniform("ScanTime", uniform::UT_FLOAT, uniform::CU_NTSC_HTIME); + ntsc_effect->add_uniform("CCValue", uniform::UT_FLOAT, uniform::CU_NTSC_CCFREQ); + ntsc_effect->add_uniform("AValue", uniform::UT_FLOAT, uniform::CU_NTSC_A); + ntsc_effect->add_uniform("BValue", uniform::UT_FLOAT, uniform::CU_NTSC_B); + ntsc_effect->add_uniform("OValue", uniform::UT_FLOAT, uniform::CU_NTSC_O); + ntsc_effect->add_uniform("PValue", uniform::UT_FLOAT, uniform::CU_NTSC_P); + ntsc_effect->add_uniform("NotchHalfWidth", uniform::UT_FLOAT, uniform::CU_NTSC_NOTCH); + ntsc_effect->add_uniform("YFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_YFREQ); + ntsc_effect->add_uniform("IFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_IFREQ); + ntsc_effect->add_uniform("QFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_QFREQ); + ntsc_effect->add_uniform("ScanTime", uniform::UT_FLOAT, uniform::CU_NTSC_HTIME); color_effect->add_uniform("RedRatios", uniform::UT_VEC3, uniform::CU_COLOR_RED_RATIOS); color_effect->add_uniform("GrnRatios", uniform::UT_VEC3, uniform::CU_COLOR_GRN_RATIOS); @@ -1062,8 +1050,7 @@ void shaders::begin_draw() focus_effect->set_technique("DefaultTechnique"); deconverge_effect->set_technique("DefaultTechnique"); color_effect->set_technique("DefaultTechnique"); - yiq_encode_effect->set_technique("DefaultTechnique"); - yiq_decode_effect->set_technique("DefaultTechnique"); + ntsc_effect->set_technique("DefaultTechnique"); color_effect->set_technique("DefaultTechnique"); bloom_effect->set_technique("DefaultTechnique"); downsample_effect->set_technique("DefaultTechnique"); @@ -1244,27 +1231,16 @@ int shaders::ntsc_pass(render_target *rt, int source_index, poly_info *poly, int { return next_index; } - - float frame_offset = curr_texture->get_cur_frame() == 0 - ? 0.0f - : (float)curr_texture->get_cur_frame(); - - // Convert our signal into YIQ - curr_effect = yiq_encode_effect; - curr_effect->update_uniforms(); - curr_effect->set_float("FrameOffset", frame_offset); - // initial "Diffuse" texture is set in shaders::set_texture() + float signal_offset = curr_texture->get_cur_frame() == 0 + ? 0.0f + : options->yiq_jitter; - next_index = rt->next_index(next_index); - blit(rt->native_target[next_index], true, D3DPT_TRIANGLELIST, 0, 2); + // initial "Diffuse" texture is set in shaders::set_texture() - // Convert our signal from YIQ - curr_effect = yiq_decode_effect; + curr_effect = ntsc_effect; curr_effect->update_uniforms(); - curr_effect->set_texture("Composite", rt->native_texture[next_index]); - curr_effect->set_texture("Diffuse", curr_texture->get_finaltex()); - curr_effect->set_float("FrameOffset", frame_offset); + curr_effect->set_float("SignalOffset", signal_offset); next_index = rt->next_index(next_index); blit(rt->native_target[next_index], true, D3DPT_TRIANGLELIST, 0, 2); @@ -1457,7 +1433,9 @@ int shaders::post_pass(render_target *rt, int source_index, poly_info *poly, int curr_effect->set_vector("BackColor", 3, back_color); curr_effect->set_vector("ScreenScale", 2, screen_scale); curr_effect->set_vector("ScreenOffset", 2, screen_offset); - curr_effect->set_float("ScanlineOffset", curr_texture->get_cur_frame() == 0 ? 0.0f : options->scanline_offset); + curr_effect->set_float("ScanlineOffset", curr_texture->get_cur_frame() == 0 ? 0.0f : options->scanline_jitter); + curr_effect->set_float("TimeMilliseconds", (float)machine->time().as_double() * 1000.0f); + curr_effect->set_float("HumBarAlpha", options->hum_bar_alpha); curr_effect->set_bool("PrepareBloom", prepare_bloom); curr_effect->set_bool("PrepareVector", prepare_vector); @@ -2159,15 +2137,10 @@ void shaders::delete_resources(bool reset) delete color_effect; color_effect = NULL; } - if (yiq_encode_effect != NULL) - { - delete yiq_encode_effect; - yiq_encode_effect = NULL; - } - if (yiq_decode_effect != NULL) + if (ntsc_effect != NULL) { - delete yiq_decode_effect; - yiq_decode_effect = NULL; + delete ntsc_effect; + ntsc_effect = NULL; } if (backbuffer != NULL) @@ -2423,10 +2396,16 @@ static INT32 slider_scanline_bright_offset(running_machine &machine, void *arg, return slider_set(&(((hlsl_options*)arg)->scanline_bright_offset), 0.05f, "%2.2f", str, newval); } -static INT32 slider_scanline_offset(running_machine &machine, void *arg, std::string *str, INT32 newval) +static INT32 slider_scanline_jitter(running_machine &machine, void *arg, std::string *str, INT32 newval) { ((hlsl_options*)arg)->params_dirty = true; - return slider_set(&(((hlsl_options*)arg)->scanline_offset), 0.05f, "%2.2f", str, newval); + return slider_set(&(((hlsl_options*)arg)->scanline_jitter), 0.01f, "%1.2f", str, newval); +} + +static INT32 slider_hum_bar_alpha(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->hum_bar_alpha), 0.01f, "%1.2f", str, newval); } static INT32 slider_defocus_x(running_machine &machine, void *arg, std::string *str, INT32 newval) @@ -2781,6 +2760,105 @@ static INT32 slider_bloom_lvl10_scale(running_machine &machine, void *arg, std:: return slider_set(&(((hlsl_options*)arg)->bloom_level10_weight), 0.01f, "%1.2f", str, newval); } + +static INT32 slider_ntsc_enable(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + hlsl_options *options = (hlsl_options*)arg; + if (newval != SLIDER_NOCHANGE) + { + options->yiq_enable = newval; + } + if (str != NULL) + { + strprintf(*str, "%s", options->yiq_enable == 0 ? "Off" : "On"); + } + options->params_dirty = true; + + return options->yiq_enable; +} + +// static INT32 slider_ntsc_phase_count(running_machine &machine, void *arg, std::string *str, INT32 newval) +// { +// hlsl_options *options = (hlsl_options*)arg; +// if (newval != SLIDER_NOCHANGE) +// { +// options->yiq_phase_count = newval; +// } +// if (str != NULL) +// { +// strprintf(*str, "%d", options->yiq_phase_count); +// } +// options->params_dirty = true; + +// return options->yiq_phase_count; +// } + +static INT32 slider_ntsc_jitter(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->yiq_jitter), 0.01f, "%1.2f", str, newval); +} + +static INT32 slider_ntsc_a_value(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->yiq_a), 0.01f, "%1.2f", str, newval); +} + +static INT32 slider_ntsc_b_value(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->yiq_b), 0.01f, "%1.2f", str, newval); +} + +static INT32 slider_ntsc_p_value(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->yiq_p), 0.01f, "%1.2f", str, newval); +} + +static INT32 slider_ntsc_o_value(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->yiq_o), 0.01f, "%1.2f", str, newval); +} + +static INT32 slider_ntsc_cc_value(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->yiq_cc), 0.0001f, "%1.4f", str, newval); +} + +static INT32 slider_ntsc_n_value(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->yiq_n), 0.01f, "%1.4f", str, newval); +} + +static INT32 slider_ntsc_y_value(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->yiq_y), 0.01f, "%1.4f", str, newval); +} + +static INT32 slider_ntsc_i_value(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->yiq_i), 0.01f, "%1.4f", str, newval); +} + +static INT32 slider_ntsc_q_value(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->yiq_q), 0.01f, "%1.4f", str, newval); +} + +static INT32 slider_ntsc_scan_time(running_machine &machine, void *arg, std::string *str, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->yiq_scan_time), 0.01f, "%1.2f", str, newval); +} + hlsl_options shaders::last_options = { false }; shaders::slider_desc shaders::s_sliders[] = @@ -2805,7 +2883,8 @@ shaders::slider_desc shaders::s_sliders[] = { "Scanline Indiv. Height", 1, 20, 80, 1, 5, slider_scanline_height }, { "Scanline Brightness", 0, 20, 40, 1, 5, slider_scanline_bright_scale }, { "Scanline Brightness Overdrive", 0, 0, 20, 1, 5, slider_scanline_bright_offset }, - { "Scanline Jitter", 0, 0, 40, 1, 5, slider_scanline_offset }, + { "Scanline Jitter", 0, 0, 100, 1, 5, slider_scanline_jitter }, + { "Hum Bar Darkness", 0, 0, 100, 1, 5, slider_hum_bar_alpha }, { "Defocus X", 0, 0, 100, 1, 7, slider_defocus_x }, { "Defocus Y", 0, 0, 100, 1, 7, slider_defocus_y }, { "Red Position Offset X", -100, 0, 100, 1, 7, slider_red_converge_x }, @@ -2861,6 +2940,19 @@ shaders::slider_desc shaders::s_sliders[] = { "Bloom Level 8 Scale", 0, 0, 100, 1, 7, slider_bloom_lvl8_scale }, { "Bloom Level 9 Scale", 0, 0, 100, 1, 7, slider_bloom_lvl9_scale }, { "Bloom Level 10 Scale", 0, 0, 100, 1, 7, slider_bloom_lvl10_scale }, + { "NTSC processing", 0, 0, 1, 1, 5, slider_ntsc_enable }, + { "Signal Jitter", 0, 0, 100, 1, 5, slider_ntsc_jitter }, + { "A Value", -100, 50, 100, 1, 5, slider_ntsc_a_value }, + { "B Value", -100, 50, 100, 1, 5, slider_ntsc_b_value }, + { "Incoming Pixel Clock Scaling", -300, 100, 300, 1, 5, slider_ntsc_p_value }, + { "Outgoing Color Carrier Phase", -300, 0, 300, 1, 5, slider_ntsc_o_value }, + { "Color Carrier Frequency", 0, 35795, 60000, 5, 5, slider_ntsc_cc_value }, + { "Y Notch", 0, 100, 600, 5, 5, slider_ntsc_n_value }, + { "Y Frequency", 0, 600, 600, 5, 5, slider_ntsc_y_value }, + { "I Frequency", 0, 120, 600, 5, 5, slider_ntsc_i_value }, + { "Q Frequency", 0, 60, 600, 5, 5, slider_ntsc_q_value }, + { "Scanline Duration", 0, 5260, 10000, 1, 5, slider_ntsc_scan_time }, + // { "Phase Count", 1, 2, 3, 1, 5, slider_ntsc_phase_count }, { NULL, 0, 0, 0, 0, 0, NULL }, }; diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h index a6d71f27d37..d949c1417c8 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.h +++ b/src/osd/modules/render/d3d/d3dhlsl.h @@ -210,7 +210,8 @@ struct hlsl_options float scanline_height; float scanline_bright_scale; float scanline_bright_offset; - float scanline_offset; + float scanline_jitter; + float hum_bar_alpha; float defocus[2]; float converge_x[3]; float converge_y[3]; @@ -228,6 +229,7 @@ struct hlsl_options // NTSC bool yiq_enable; + float yiq_jitter; float yiq_cc; float yiq_a; float yiq_b; @@ -427,8 +429,7 @@ private: effect * phosphor_effect; // pointer to the phosphor-effect object effect * deconverge_effect; // pointer to the deconvergence-effect object effect * color_effect; // pointer to the color-effect object - effect * yiq_encode_effect; // pointer to the YIQ encoder effect object - effect * yiq_decode_effect; // pointer to the YIQ decoder effect object + effect * ntsc_effect; // pointer to the NTSC effect object effect * bloom_effect; // pointer to the bloom composite effect effect * downsample_effect; // pointer to the bloom downsample effect effect * vector_effect; // pointer to the vector-effect object diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp index 72682c177c4..27907f49783 100644 --- a/src/osd/windows/winmain.cpp +++ b/src/osd/windows/winmain.cpp @@ -303,12 +303,13 @@ const options_entry windows_options::s_option_entries[] = { WINOPTION_REFLECTION";fs_ref(0.0-1.0)", "0.0", OPTION_FLOAT, "screen reflection amount" }, { WINOPTION_VIGNETTING";fs_vig(0.0-1.0)", "0.0", OPTION_FLOAT, "image vignetting amount" }, /* Beam-related values below this line*/ - { WINOPTION_SCANLINE_AMOUNT";fs_scanam(0.0-4.0)", "1.0", OPTION_FLOAT, "overall alpha scaling value for scanlines" }, + { WINOPTION_SCANLINE_AMOUNT";fs_scanam(0.0-4.0)", "0.0", OPTION_FLOAT, "overall alpha scaling value for scanlines" }, { WINOPTION_SCANLINE_SCALE";fs_scansc(0.0-4.0)", "1.0", OPTION_FLOAT, "overall height scaling value for scanlines" }, { WINOPTION_SCANLINE_HEIGHT";fs_scanh(0.0-4.0)", "1.0", OPTION_FLOAT, "individual height scaling value for scanlines" }, { WINOPTION_SCANLINE_BRIGHT_SCALE";fs_scanbs(0.0-2.0)", "1.0", OPTION_FLOAT, "overall brightness scaling value for scanlines (multiplicative)" }, { WINOPTION_SCANLINE_BRIGHT_OFFSET";fs_scanbo(0.0-1.0)", "0.0", OPTION_FLOAT, "overall brightness offset value for scanlines (additive)" }, - { WINOPTION_SCANLINE_OFFSET";fs_scanjt(0.0-4.0)", "0.0", OPTION_FLOAT, "overall interlace jitter scaling value for scanlines" }, + { WINOPTION_SCANLINE_JITTER";fs_scanjt(0.0-4.0)", "0.0", OPTION_FLOAT, "overall interlace jitter scaling value for scanlines" }, + { WINOPTION_HUM_BAR_ALPHA";fs_humba(0.0-1.0)", "0.0", OPTION_FLOAT, "overall alpha scaling value for hum bar" }, { WINOPTION_DEFOCUS";fs_focus", "1.0,0.0", OPTION_STRING, "overall defocus value in screen-relative coords" }, { WINOPTION_CONVERGE_X";fs_convx", "0.25,0.00,-0.25", OPTION_STRING, "convergence in screen-relative X direction" }, { WINOPTION_CONVERGE_Y";fs_convy", "0.0,0.25,-0.25", OPTION_STRING, "convergence in screen-relative Y direction" }, @@ -327,10 +328,11 @@ const options_entry windows_options::s_option_entries[] = /* NTSC simulation below this line */ { NULL, NULL, OPTION_HEADER, "NTSC POST-PROCESSING OPTIONS" }, { WINOPTION_YIQ_ENABLE";yiq", "0", OPTION_BOOLEAN, "enables YIQ-space HLSL post-processing" }, - { WINOPTION_YIQ_CCVALUE";yiqcc", "3.59754545", OPTION_FLOAT, "Color Carrier frequency for NTSC signal processing" }, + { WINOPTION_YIQ_JITTER";yiqj", "0.0", OPTION_FLOAT, "Jitter for the NTSC signal processing" }, + { WINOPTION_YIQ_CCVALUE";yiqcc", "3.57954545", OPTION_FLOAT, "Color Carrier frequency for NTSC signal processing" }, { WINOPTION_YIQ_AVALUE";yiqa", "0.5", OPTION_FLOAT, "A value for NTSC signal processing" }, { WINOPTION_YIQ_BVALUE";yiqb", "0.5", OPTION_FLOAT, "B value for NTSC signal processing" }, - { WINOPTION_YIQ_OVALUE";yiqo", "1.0", OPTION_FLOAT, "Outgoing Color Carrier phase offset for NTSC signal processing" }, + { WINOPTION_YIQ_OVALUE";yiqo", "0.0", OPTION_FLOAT, "Outgoing Color Carrier phase offset for NTSC signal processing" }, { WINOPTION_YIQ_PVALUE";yiqp", "1.0", OPTION_FLOAT, "Incoming Pixel Clock scaling value for NTSC signal processing" }, { WINOPTION_YIQ_NVALUE";yiqn", "1.0", OPTION_FLOAT, "Y filter notch width for NTSC signal processing" }, { WINOPTION_YIQ_YVALUE";yiqy", "6.0", OPTION_FLOAT, "Y filter cutoff frequency for NTSC signal processing" }, diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h index 53f9e137604..a9f7066bf90 100644 --- a/src/osd/windows/winmain.h +++ b/src/osd/windows/winmain.h @@ -55,7 +55,8 @@ #define WINOPTION_SCANLINE_HEIGHT "scanline_height" #define WINOPTION_SCANLINE_BRIGHT_SCALE "scanline_bright_scale" #define WINOPTION_SCANLINE_BRIGHT_OFFSET "scanline_bright_offset" -#define WINOPTION_SCANLINE_OFFSET "scanline_jitter" +#define WINOPTION_SCANLINE_JITTER "scanline_jitter" +#define WINOPTION_HUM_BAR_ALPHA "hum_bar_alpha" #define WINOPTION_DEFOCUS "defocus" #define WINOPTION_CONVERGE_X "converge_x" #define WINOPTION_CONVERGE_Y "converge_y" @@ -71,6 +72,7 @@ #define WINOPTION_PHOSPHOR "phosphor_life" #define WINOPTION_SATURATION "saturation" #define WINOPTION_YIQ_ENABLE "yiq_enable" +#define WINOPTION_YIQ_JITTER "yiq_jitter" #define WINOPTION_YIQ_CCVALUE "yiq_cc" #define WINOPTION_YIQ_AVALUE "yiq_a" #define WINOPTION_YIQ_BVALUE "yiq_b" @@ -154,7 +156,8 @@ public: float screen_scanline_height() const { return float_value(WINOPTION_SCANLINE_HEIGHT); } float screen_scanline_bright_scale() const { return float_value(WINOPTION_SCANLINE_BRIGHT_SCALE); } float screen_scanline_bright_offset() const { return float_value(WINOPTION_SCANLINE_BRIGHT_OFFSET); } - float screen_scanline_offset() const { return float_value(WINOPTION_SCANLINE_OFFSET); } + float screen_scanline_jitter() const { return float_value(WINOPTION_SCANLINE_JITTER); } + float screen_hum_bar_alpha() const { return float_value(WINOPTION_HUM_BAR_ALPHA); } float screen_reflection() const { return float_value(WINOPTION_REFLECTION); } float screen_curvature() const { return float_value(WINOPTION_CURVATURE); } float screen_round_corner() const { return float_value(WINOPTION_ROUND_CORNER); } @@ -169,6 +172,7 @@ public: const char *screen_grn_ratio() const { return value(WINOPTION_GRN_RATIO); } const char *screen_blu_ratio() const { return value(WINOPTION_BLU_RATIO); } bool screen_yiq_enable() const { return bool_value(WINOPTION_YIQ_ENABLE); } + float screen_yiq_jitter() const { return float_value(WINOPTION_YIQ_JITTER); } float screen_yiq_cc() const { return float_value(WINOPTION_YIQ_CCVALUE); } float screen_yiq_a() const { return float_value(WINOPTION_YIQ_AVALUE); } float screen_yiq_b() const { return float_value(WINOPTION_YIQ_BVALUE); } -- cgit v1.2.3-70-g09d2