summaryrefslogtreecommitdiffstatshomepage
path: root/hlsl
diff options
context:
space:
mode:
Diffstat (limited to 'hlsl')
-rw-r--r--hlsl/artwork_support/post.fx30
-rw-r--r--hlsl/ntsc.fx (renamed from hlsl/yiq_decode.fx)142
-rw-r--r--hlsl/post.fx30
-rw-r--r--hlsl/yiq_encode.fx151
4 files changed, 134 insertions, 219 deletions
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/yiq_decode.fx b/hlsl/ntsc.fx
index 288d00b2312..ed07e37a4cc 100644
--- a/hlsl/yiq_decode.fx
+++ b/hlsl/ntsc.fx
@@ -1,26 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz,ImJezze
//-----------------------------------------------------------------------------
-// YIQ Decode Effect
+// NTSC Effect
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Sampler Definitions
//-----------------------------------------------------------------------------
-texture Composite;
-
-sampler CompositeSampler = sampler_state
-{
- Texture = <Composite>;
- MipFilter = POINT;
- MinFilter = POINT;
- MagFilter = POINT;
- AddressU = CLAMP;
- AddressV = CLAMP;
- AddressW = CLAMP;
-};
-
texture Diffuse;
sampler DiffuseSampler = sampler_state
@@ -81,51 +68,90 @@ VS_OUTPUT vs_main(VS_INPUT Input)
}
//-----------------------------------------------------------------------------
-// YIQ Decode Pixel Shader
+// NTSC Pixel Shader
//-----------------------------------------------------------------------------
uniform float AValue = 0.5f;
uniform float BValue = 0.5f;
-uniform float CCValue = 3.5975454f;
+uniform float CCValue = 3.5795454f;
uniform float OValue = 0.0f;
-uniform float PValue = 1.0f; // unused
-
+uniform float PValue = 1.0f;
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;
+uniform float SignalOffset = 0.0f;
+
//-----------------------------------------------------------------------------
// 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 PI2 = PI * 2.0f;
-static const float MaxC = 2.1183f;
-static const float MinC = -1.1183f;
-static const float CRange = 3.2366f;
+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);
-float4 ps_main(PS_INPUT Input) : COLOR
+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)
{
- float4 BaseTexel = tex2D(DiffuseSampler, Input.TexCoord.xy);
+ float2 SourceTexelDims = 1.0f / SourceDims;
+ float2 SourceRes = SourceDims * SourceRect;
- float2 InvDims = 1.0f / SourceDims;
+ float2 PValueSourceTexel = float2(PValue, 0.0f) * SourceTexelDims;
- // YIQ convolution: N coefficients each
- float4 YAccum = 0.0f;
- float4 IAccum = 0.0f;
- float4 QAccum = 0.0f;
+ 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);
- float BValueFrameOffset = BValue * FrameOffset;
+ float2 SourceTexelDims = 1.0f / SourceDims;
+ float2 SourceRes = SourceDims * SourceRect;
- float FrameWidthx4 = SourceDims.x * SourceRect.x * 4.0f;
- float TimePerSample = ScanTime / FrameWidthx4;
+ float TimePerSample = ScanTime / (SourceRes.x * 4.0f);
float Fc_y1 = (CCValue - NotchHalfWidth) * TimePerSample;
float Fc_y2 = (CCValue + NotchHalfWidth) * TimePerSample;
@@ -142,24 +168,34 @@ float4 ps_main(PS_INPUT Input) : COLOR
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 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 * (SourceDims.y * SourceRect.y) * 2.0f;
+ float4 VPosition = Cy / SourceRect.y;
- for(float n = -41.0f; n < 42.0f; n += 4.0f)
+ for (float i = 0; i < SampleCount; i += 4.0f)
{
+ float n = i - HalfSampleCount;
+
float4 n4 = n + NotchOffset;
- float4 Cx = Input.TexCoord.x + InvDims.x * n4 * 0.25f;
- float4 HPosition = (Cx / SourceRect.x);
+ float4 Cx = Input.TexCoord.x + SourceTexelDims.x * (n4 * 0.25f);
+ float4 HPosition = Cx / SourceRect.x;
- float4 C = tex2D(CompositeSampler, float2(Cx.r, Cy.r)) * CRange + MinC;
+ float4 C = GetCompositeYIQ(float2(Cx.r, Cy.r));
- float4 T = HPosition + AValue * VPosition + BValueFrameOffset;
- float4 WT = W * T + OValue;
+ 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);
@@ -186,21 +222,21 @@ float4 ps_main(PS_INPUT Input) : COLOR
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(
+ (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 YIQ = float3(Y, I, Q);
+ float3 RGB = float3(
+ dot(YIQ, RDot),
+ dot(YIQ, GDot),
+ dot(YIQ, BDot));
- 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);
+ return float4(RGB, BaseTexel.a);
}
//-----------------------------------------------------------------------------
-// YIQ Decode Technique
+// NTSC Technique
//-----------------------------------------------------------------------------
technique DefaultTechnique
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_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 = <Diffuse>;
- 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();
- }
-}