diff options
author | Ryan Holtz <rholtz@batcountryentertainment.com> | 2011-05-30 21:10:23 +0000 |
---|---|---|
committer | Ryan Holtz <rholtz@batcountryentertainment.com> | 2011-05-30 21:10:23 +0000 |
commit | 796e691522ba5c47fc0610da4f557514563f85b9 (patch) | |
tree | 961683497fd1e4d7369da812c579572f880b188a /hlsl/yiq_decode.fx | |
parent | e532e74a8a869af6da71222657f39684210b624e (diff) |
HLSL Updates: [Ryan Holtz, Bat Country Entertainment, austere, SoltanGris42]
- Added the ability to render screenshots at arbitrary resolutions.
- Added the ability to record AVI videos (albeit with no audio) at arbitrary resolutions.
- Added a 43-tap-wide FIR-based NTSC filter with tunable Y, I and Q frequency response.
- Updated scanlines to have a user-tunable pixel-height ratio in addition to the current screen-height ratio.
- Fixed a VRAM leak that was causing many dynamic-resolution drivers to run out of memory mid-run.
Diffstat (limited to 'hlsl/yiq_decode.fx')
-rw-r--r-- | hlsl/yiq_decode.fx | 163 |
1 files changed, 52 insertions, 111 deletions
diff --git a/hlsl/yiq_decode.fx b/hlsl/yiq_decode.fx index 550a0a83062..a85590d998f 100644 --- a/hlsl/yiq_decode.fx +++ b/hlsl/yiq_decode.fx @@ -20,9 +20,9 @@ texture Diffuse; sampler DiffuseSampler = sampler_state { Texture = <Diffuse>; - MipFilter = POINT; - MinFilter = POINT; - MagFilter = POINT; + MipFilter = LINEAR; + MinFilter = LINEAR; + MagFilter = LINEAR; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; @@ -35,15 +35,7 @@ sampler DiffuseSampler = sampler_state struct VS_OUTPUT { float4 Position : POSITION; - float4 Color : COLOR0; float4 Coord0 : TEXCOORD0; - float4 Coord1 : TEXCOORD1; - float4 Coord2 : TEXCOORD2; - float4 Coord3 : TEXCOORD3; - float4 Coord4 : TEXCOORD4; - float4 Coord5 : TEXCOORD5; - float4 Coord6 : TEXCOORD6; - float4 Coord7 : TEXCOORD7; }; struct VS_INPUT @@ -55,15 +47,7 @@ struct VS_INPUT struct PS_INPUT { - float4 Color : COLOR0; float4 Coord0 : TEXCOORD0; - float4 Coord1 : TEXCOORD1; - float4 Coord2 : TEXCOORD2; - float4 Coord3 : TEXCOORD3; - float4 Coord4 : TEXCOORD4; - float4 Coord5 : TEXCOORD5; - float4 Coord6 : TEXCOORD6; - float4 Coord7 : TEXCOORD7; }; //----------------------------------------------------------------------------- @@ -79,8 +63,6 @@ uniform float RawHeight; uniform float WidthRatio; uniform float HeightRatio; -uniform float FscValue; - VS_OUTPUT vs_main(VS_INPUT Input) { VS_OUTPUT Output = (VS_OUTPUT)0; @@ -88,25 +70,12 @@ VS_OUTPUT vs_main(VS_INPUT Input) Output.Position = float4(Input.Position.xyz, 1.0f); Output.Position.x /= TargetWidth; Output.Position.y /= TargetHeight; - //Output.Position.x /= WidthRatio; - //Output.Position.y /= HeightRatio; Output.Position.y = 1.0f - Output.Position.y; Output.Position.x -= 0.5f; Output.Position.y -= 0.5f; Output.Position *= float4(2.0f, 2.0f, 1.0f, 1.0f); - Output.Color = Input.Color; - Output.Coord0.xy = Input.TexCoord + float2(0.00f / RawWidth, 0.0f); - Output.Coord1.xy = Input.TexCoord + float2(0.25f / RawWidth, 0.0f); - Output.Coord2.xy = Input.TexCoord + float2(0.50f / RawWidth, 0.0f); - Output.Coord3.xy = Input.TexCoord + float2(0.75f / RawWidth, 0.0f); - Output.Coord4.xy = Input.TexCoord + float2(1.00f / RawWidth, 0.0f); - Output.Coord5.xy = Input.TexCoord + float2(1.25f / RawWidth, 0.0f); - Output.Coord6.xy = Input.TexCoord + float2(1.50f / RawWidth, 0.0f); - Output.Coord7.xy = Input.TexCoord + float2(1.75f / RawWidth, 0.0f); - Output.Coord0.zw = Input.TexCoord + float2(2.00f / RawWidth, 0.0f); - Output.Coord1.zw = Input.TexCoord + float2(2.25f / RawWidth, 0.0f); - Output.Coord2.zw = Input.TexCoord + float2(2.50f / RawWidth, 0.0f); - Output.Coord3.zw = Input.TexCoord + float2(2.75f / RawWidth, 0.0f); + Output.Coord0.xy = Input.TexCoord + 0.5f / float2(RawWidth, RawHeight); + Output.Coord0.zw = float2(1.0f / RawWidth, 0.0f); return Output; } @@ -115,95 +84,67 @@ VS_OUTPUT vs_main(VS_INPUT Input) // YIQ Decode Pixel Shader //----------------------------------------------------------------------------- -uniform float YSubsampleLength = 3.0f; -uniform float ISubsampleLength = 3.0f; -uniform float QSubsampleLength = 3.0f; +uniform float AValue = 0.0f; +uniform float BValue = 0.0f; +uniform float CCValue = 3.04183f; +uniform float PValue = 1.0f; +uniform float OValue = 0.0f; +uniform float ScanTime = 52.6f; -uniform float WValue; -uniform float AValue; -uniform float BValue; +uniform float YFreqResponse = 3.0f; +uniform float IFreqResponse = 1.2f; +uniform float QFreqResponse = 0.6f; float4 ps_main(PS_INPUT Input) : COLOR { float2 RawDims = float2(RawWidth, RawHeight); - float4 BaseTexel = tex2D(DiffuseSampler, Input.Coord0.xy + float2(0.5f, 0.5f) / RawDims); - float4 OrigC = tex2D(CompositeSampler, Input.Coord0.xy + float2(0.5f, 0.5f) / RawDims); - float4 OrigC2 = tex2D(CompositeSampler, Input.Coord4.xy + float2(0.5f, 0.5f) / RawDims); - float4 OrigC3 = tex2D(CompositeSampler, Input.Coord0.zw + float2(0.5f, 0.5f) / RawDims); - float4 C = OrigC; - float4 C2 = OrigC2; - float4 C3 = OrigC3; + float4 BaseTexel = tex2D(DiffuseSampler, Input.Coord0.xy + 0.5f / RawDims); + + // YIQ convolution: N coefficients each + float4 YAccum = 0.0f; + float4 IAccum = 0.0f; + float4 QAccum = 0.0f; float MaxC = 2.1183f; float MinC = -1.1183f; float CRange = MaxC - MinC; - - C = C * CRange + MinC; - C2 = C2 * CRange + MinC; - - float2 Coord0 = Input.Coord0.xy * RawDims; - float2 Coord1 = Input.Coord1.xy * RawDims; - float2 Coord2 = Input.Coord2.xy * RawDims; - float2 Coord3 = Input.Coord3.xy * RawDims; - float2 Coord4 = Input.Coord4.xy * RawDims; - float2 Coord5 = Input.Coord5.xy * RawDims; - float2 Coord6 = Input.Coord6.xy * RawDims; - float2 Coord7 = Input.Coord7.xy * RawDims; - float2 Coord8 = Input.Coord0.zw * RawDims; - float2 Coord9 = Input.Coord1.zw * RawDims; - float2 CoordA = Input.Coord2.zw * RawDims; - float2 CoordB = Input.Coord3.zw * RawDims; - - float W = WValue * 2.0f; - float T0 = Coord0.x + AValue * Coord0.y + BValue; - float T1 = Coord1.x + AValue * Coord1.y + BValue; - float T2 = Coord2.x + AValue * Coord2.y + BValue; - float T3 = Coord3.x + AValue * Coord3.y + BValue; - float T4 = Coord4.x + AValue * Coord4.y + BValue; - float T5 = Coord5.x + AValue * Coord5.y + BValue; - float T6 = Coord6.x + AValue * Coord6.y + BValue; - float T7 = Coord7.x + AValue * Coord7.y + BValue; - float T8 = Coord8.x + AValue * Coord8.y + BValue; - float T9 = Coord9.x + AValue * Coord9.y + BValue; - float TA = CoordA.x + AValue * CoordA.y + BValue; - float TB = CoordB.x + AValue * CoordB.y + BValue; - float4 Tc = float4(T0, T1, T2, T3); - float4 Tc2 = float4(T4, T5, T6, T7); - float4 Tc3 = float4(T8, T9, TA, TB); - - float Yvals[8]; - Yvals[0] = C.r; Yvals[1] = C.g; Yvals[2] = C.b; Yvals[3] = C.a; Yvals[4] = C2.r; Yvals[5] = C2.g; Yvals[6] = C2.b; Yvals[7] = C2.a; - float Ytotal = 0.0f; - for(uint idx = 0; idx < FscValue * 4.0f; idx++ ) + float Fc_y = YFreqResponse * ScanTime / (RawWidth * 4.0f / WidthRatio); + float Fc_i = IFreqResponse * ScanTime / (RawWidth * 4.0f / WidthRatio); + float Fc_q = QFreqResponse * ScanTime / (RawWidth * 4.0f / WidthRatio); + float PI = 3.1415926535897932384626433832795; + float PI2 = 2.0f * PI; + float PI2Length = PI2 / 42.0f; + for(float n = -21.0f; n < 22.0f; n += 4.0f) { - Ytotal = Ytotal + Yvals[idx]; + float4 n4 = float4(n + 0.0f, n + 1.0f, n + 2.0f, n + 3.0f); + float4 CoordX = Input.Coord0.x + Input.Coord0.z * n4 * 0.25f; + float4 CoordY = Input.Coord0.y; + float4 C = tex2D(CompositeSampler, float2(CoordX.r, CoordY.r)) * CRange + MinC; + float4 WT = PI2 * CCValue * ScanTime * (CoordX * WidthRatio + AValue * CoordY * 2.0f * (RawHeight / HeightRatio) + BValue) + OValue; + + float4 SincYIn = PI2 * Fc_y * n4; + float4 IdealY = 2.0f * Fc_y * ((SincYIn != 0.0f) ? (sin(SincYIn) / SincYIn) : 1.0f); + float4 FilterY = (0.54f + 0.46f * cos(PI2Length * n4)) * IdealY; + + float4 SincIIn = PI2 * Fc_i * n4; + float4 IdealI = 2.0f * Fc_i * ((SincIIn != 0.0f) ? (sin(SincIIn) / SincIIn) : 1.0f); + float4 FilterI = (0.54f + 0.46f * cos(PI2Length * n4)) * IdealI; + + float4 SincQIn = PI2 * Fc_q * n4; + float4 IdealQ = 2.0f * Fc_q * ((SincQIn != 0.0f) ? (sin(SincQIn) / SincQIn) : 1.0f); + float4 FilterQ = (0.54f + 0.46f * cos(PI2Length * n4)) * IdealQ; + + YAccum = YAccum + C * FilterY; + IAccum = IAccum + C * cos(WT) * FilterI; + QAccum = QAccum + C * sin(WT) * FilterQ; } - float Yavg = Ytotal / (FscValue * 4.0f); - - float4 I = (C - Yavg) * sin(W * Tc); - float4 Q = (C - Yavg) * cos(W * Tc); - float4 I2 = (C2 - Yavg) * sin(W * Tc2); - float4 Q2 = (C2 - Yavg) * cos(W * Tc2); - float4 I3 = (C3 - Yavg) * sin(W * Tc3); - float4 Q3 = (C3 - Yavg) * cos(W * Tc3); - float Itotal = 0.0f; - float Qtotal = 0.0f; + 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; - float Ivals[8]; - float Qvals[8]; - Ivals[0] = I.r; Ivals[1] = I.g; Ivals[2] = I.b; Ivals[3] = I.a; Ivals[4] = I2.r; Ivals[5] = I2.g; Ivals[6] = I2.b; Ivals[7] = I2.a; - Qvals[0] = Q.r; Qvals[1] = Q.g; Qvals[2] = Q.b; Qvals[3] = Q.a; Qvals[4] = Q2.r; Qvals[5] = Q2.g; Qvals[6] = Q2.b; Qvals[7] = Q2.a; - for(uint idx = 0; idx < FscValue * 4.0f; idx++ ) - { - Itotal = Itotal + Ivals[idx]; - Qtotal = Qtotal + Qvals[idx]; - } - float Iavg = Itotal / (FscValue * 3.0f); - float Qavg = Qtotal / (FscValue * 3.0f); + float3 YIQ = float3(Y, I, Q); - float3 YIQ = float3(Yavg, Iavg * 1.5f, Qavg); - float3 OutRGB = 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(OutRGB, BaseTexel.a); |