diff options
author | 2011-06-06 21:25:38 +0000 | |
---|---|---|
committer | 2011-06-06 21:25:38 +0000 | |
commit | 1ec454197a94b693b67f8b9d8bb702288b1478fe (patch) | |
tree | 9010ee023db94a28dde5ac5f5d5edaa5e38beb58 | |
parent | 1d33744bd45f67fd1bd6f1a71aaa42db5d49a138 (diff) |
HLSL Updates: [Ryan Holtz, Bat Country Entertainment, austere]
- Reworked default shadow mask settings, eliminating rainbow banding and matching reference shots more closely
- Moved color power to occur after shadow mask, as it is intended to simulate nonlinear phosphor response
- Added a variable-width notch filter to the Y channel in NTSC post-processing, eliminating luma banding on e.g. CoCo 2 and Apple II
-rw-r--r-- | artwork/aperture.png | bin | 305 -> 271 bytes | |||
-rw-r--r-- | hlsl/color.fx | 8 | ||||
-rw-r--r-- | hlsl/post.fx | 10 | ||||
-rw-r--r-- | hlsl/yiq_decode.fx | 22 | ||||
-rw-r--r-- | src/osd/windows/d3dhlsl.c | 8 | ||||
-rw-r--r-- | src/osd/windows/winmain.c | 21 | ||||
-rw-r--r-- | src/osd/windows/winmain.h | 2 |
7 files changed, 42 insertions, 29 deletions
diff --git a/artwork/aperture.png b/artwork/aperture.png Binary files differindex d94aa881c48..2243dc52c6e 100644 --- a/artwork/aperture.png +++ b/artwork/aperture.png diff --git a/hlsl/color.fx b/hlsl/color.fx index e4aa954e8b5..e7ceeb57978 100644 --- a/hlsl/color.fx +++ b/hlsl/color.fx @@ -100,10 +100,6 @@ uniform float BluFloor = 0.0f; uniform float Saturation = 1.0f; -uniform float RedPower = 2.2f; -uniform float GrnPower = 2.2f; -uniform float BluPower = 2.2f; - float4 ps_main(PS_INPUT Input) : COLOR { float4 BaseTexel = tex2D(DiffuseSampler, Input.TexCoord); @@ -126,10 +122,6 @@ float4 ps_main(PS_INPUT Input) : COLOR float3 OutChroma = OutTexel - OutLuma; float3 Saturated = OutLuma + OutChroma * Saturation; - OutRGB.r = pow(Saturated.r, RedPower); - OutRGB.g = pow(Saturated.g, GrnPower); - OutRGB.b = pow(Saturated.b, BluPower); - return float4(OutRGB, BaseTexel.a); } diff --git a/hlsl/post.fx b/hlsl/post.fx index 6a148637805..eee6aaa4798 100644 --- a/hlsl/post.fx +++ b/hlsl/post.fx @@ -119,6 +119,10 @@ uniform float BluFloor = 0.0f; uniform float SnapX = 0.0f; uniform float SnapY = 0.0f; +uniform float RedPower = 2.2f; +uniform float GrnPower = 2.2f; +uniform float BluPower = 2.2f; + float4 ps_main(PS_INPUT Input) : COLOR { float2 Ratios = float2(WidthRatio, HeightRatio); @@ -174,13 +178,17 @@ float4 ps_main(PS_INPUT Input) : COLOR float2 ShadowDims = float2(ShadowWidth, ShadowHeight); float2 ShadowUV = float2(ShadowU, ShadowV); float2 ShadowMaskSize = float2(ShadowMaskSizeX, ShadowMaskSizeY); - float2 ShadowFrac = frac(BaseCoord * ShadowMaskSize * 0.5f); + float2 ShadowFrac = frac(BaseCoord * ShadowMaskSize); float2 ShadowCoord = ShadowFrac * ShadowUV + float2(1.5f / ShadowWidth, 1.5f / ShadowHeight); float3 ShadowTexel = lerp(1.0f, tex2D(ShadowSampler, ShadowCoord).rgb, UseShadow); // -- Final Pixel -- float4 Output = float4(Scanned * lerp(1.0f, ShadowTexel, ShadowBrightness), BaseTexel.a) * Input.Color; + Output.r = pow(Output.r, RedPower); + Output.g = pow(Output.g, GrnPower); + Output.b = pow(Output.b, BluPower); + return Output; } diff --git a/hlsl/yiq_decode.fx b/hlsl/yiq_decode.fx index 61ba590717a..c94ae76de0d 100644 --- a/hlsl/yiq_decode.fx +++ b/hlsl/yiq_decode.fx @@ -91,7 +91,8 @@ uniform float PValue = 1.0f; uniform float OValue = 0.0f; uniform float ScanTime = 52.6f; -uniform float YFreqResponse = 3.0f; +uniform float NotchHalfWidth = 1.0f; +uniform float YFreqResponse = 6.0f; uniform float IFreqResponse = 1.2f; uniform float QFreqResponse = 0.6f; @@ -108,15 +109,17 @@ float4 ps_main(PS_INPUT Input) : COLOR float MaxC = 2.1183f; float MinC = -1.1183f; float CRange = MaxC - MinC; - float Fc_y = YFreqResponse * ScanTime / (RawWidth * 4.0f / WidthRatio); + float Fc_y1 = (CCValue - NotchHalfWidth) * ScanTime / (RawWidth * 4.0f / WidthRatio); + float Fc_y2 = (CCValue + NotchHalfWidth) * ScanTime / (RawWidth * 4.0f / WidthRatio); + float Fc_y3 = 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; + float PI2Length = PI2 / 82.0f; float4 NOffset = float4(0.0f, 1.0f, 2.0f, 3.0f); float W = PI2 * CCValue * ScanTime; - for(float n = -21.0f; n < 22.0f; n += 4.0f) + for(float n = -41.0f; n < 42.0f; n += 4.0f) { float4 n4 = n + NOffset; float4 CoordX = Input.Coord0.x + Input.Coord0.z * n4 * 0.25f; @@ -125,9 +128,14 @@ float4 ps_main(PS_INPUT Input) : COLOR float4 C = tex2D(CompositeSampler, TexCoord + float2(0.625f, 0.4f) / RawDims) * CRange + MinC; float4 WT = W * (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 SincYIn1 = PI2 * Fc_y1 * n4; + float4 SincYIn2 = PI2 * Fc_y2 * n4; + float4 SincYIn3 = PI2 * Fc_y3 * 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 = (2.0f * Fc_y1 * SincY1 - 2.0f * Fc_y2 * SincY2) + 2.0f * Fc_y3 * SincY3; + 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); diff --git a/src/osd/windows/d3dhlsl.c b/src/osd/windows/d3dhlsl.c index 1269105e8c3..0182852ee8d 100644 --- a/src/osd/windows/d3dhlsl.c +++ b/src/osd/windows/d3dhlsl.c @@ -1016,6 +1016,9 @@ void hlsl_info::init_effect_info(d3d_poly_info *poly) (*d3dintf->effect.set_float)(curr_effect, "ScanlineBrightScale", options->scanline_bright_scale); (*d3dintf->effect.set_float)(curr_effect, "ScanlineBrightOffset", options->scanline_bright_offset); (*d3dintf->effect.set_float)(curr_effect, "ScanlineOffset", (poly->texture->cur_frame == 0) ? 0.0f : options->scanline_offset); + (*d3dintf->effect.set_float)(curr_effect, "RedPower", options->red_power); + (*d3dintf->effect.set_float)(curr_effect, "GrnPower", options->green_power); + (*d3dintf->effect.set_float)(curr_effect, "BluPower", options->blue_power); } else { @@ -1062,6 +1065,7 @@ void hlsl_info::render_quad(d3d_poly_info *poly, int vertnum) (*d3dintf->effect.set_float)(curr_effect, "AValue", winoptions.screen_yiq_a()); (*d3dintf->effect.set_float)(curr_effect, "BValue", (poly->texture->cur_frame == 2) ? 0.0f : ((float)poly->texture->cur_frame * winoptions.screen_yiq_b())); (*d3dintf->effect.set_float)(curr_effect, "PValue", winoptions.screen_yiq_p()); + (*d3dintf->effect.set_float)(curr_effect, "NotchHalfWidth", winoptions.screen_yiq_n()); (*d3dintf->effect.set_float)(curr_effect, "YFreqResponse", winoptions.screen_yiq_y()); (*d3dintf->effect.set_float)(curr_effect, "IFreqResponse", winoptions.screen_yiq_i()); (*d3dintf->effect.set_float)(curr_effect, "QFreqResponse", winoptions.screen_yiq_q()); @@ -1102,6 +1106,7 @@ void hlsl_info::render_quad(d3d_poly_info *poly, int vertnum) (*d3dintf->effect.set_float)(curr_effect, "BValue", (poly->texture->cur_frame == 2) ? 0.0f : ((float)poly->texture->cur_frame * winoptions.screen_yiq_b())); (*d3dintf->effect.set_float)(curr_effect, "OValue", winoptions.screen_yiq_o()); (*d3dintf->effect.set_float)(curr_effect, "PValue", winoptions.screen_yiq_p()); + (*d3dintf->effect.set_float)(curr_effect, "NotchHalfWidth", winoptions.screen_yiq_n()); (*d3dintf->effect.set_float)(curr_effect, "YFreqResponse", winoptions.screen_yiq_y()); (*d3dintf->effect.set_float)(curr_effect, "IFreqResponse", winoptions.screen_yiq_i()); (*d3dintf->effect.set_float)(curr_effect, "QFreqResponse", winoptions.screen_yiq_q()); @@ -1156,9 +1161,6 @@ void hlsl_info::render_quad(d3d_poly_info *poly, int vertnum) (*d3dintf->effect.set_float)(curr_effect, "RedScale", options->red_scale); (*d3dintf->effect.set_float)(curr_effect, "GrnScale", options->green_scale); (*d3dintf->effect.set_float)(curr_effect, "BluScale", options->blue_scale); - (*d3dintf->effect.set_float)(curr_effect, "RedPower", options->red_power); - (*d3dintf->effect.set_float)(curr_effect, "GrnPower", options->green_power); - (*d3dintf->effect.set_float)(curr_effect, "BluPower", options->blue_power); (*d3dintf->effect.set_float)(curr_effect, "Saturation", options->saturation); HRESULT result = (*d3dintf->device.set_render_target)(d3d->device, 0, smalltarget0[poly->texture->target_index]); diff --git a/src/osd/windows/winmain.c b/src/osd/windows/winmain.c index 48e3310ae90..8a16363b398 100644 --- a/src/osd/windows/winmain.c +++ b/src/osd/windows/winmain.c @@ -333,14 +333,14 @@ const options_entry windows_options::s_option_entries[] = { WINOPTION_HLSL_PRESCALE_SIZE, "3", OPTION_INTEGER, "HLSL scaling pre-pass factor (usually 2 or 3)" }, { WINOPTION_HLSL_PRESET";(-1-5)", "-1", OPTION_INTEGER, "HLSL preset to use (0-5)" }, { WINOPTION_HLSL_WRITE, NULL, OPTION_STRING, "enable HLSL AVI writing (huge disk bandwidth suggested)" }, - { WINOPTION_HLSL_SNAP_WIDTH, "2048", OPTION_STRING, "HLSL upscaled-snapshot width" }, - { WINOPTION_HLSL_SNAP_HEIGHT, "1536", OPTION_STRING, "HLSL upscaled-snapshot height" }, + { WINOPTION_HLSL_SNAP_WIDTH, "2048", OPTION_STRING, "HLSL upscaled-snapshot width" }, + { WINOPTION_HLSL_SNAP_HEIGHT, "1536", OPTION_STRING, "HLSL upscaled-snapshot height" }, { WINOPTION_SHADOW_MASK_ALPHA";fs_shadwa(0.0-1.0)", "0.0", OPTION_FLOAT, "shadow mask alpha-blend value (1.0 is fully blended, 0.0 is no mask)" }, { WINOPTION_SHADOW_MASK_TEXTURE";fs_shadwt(0.0-1.0)", "aperture.png", OPTION_STRING, "shadow mask texture name" }, - { WINOPTION_SHADOW_MASK_COUNT_X";fs_shadww", "640", OPTION_INTEGER, "shadow mask width, in phosphor dots" }, - { WINOPTION_SHADOW_MASK_COUNT_Y";fs_shadwh", "480", OPTION_INTEGER, "shadow mask height, in phosphor dots" }, - { WINOPTION_SHADOW_MASK_USIZE";fs_shadwu(0.0-1.0)", "0.1875", OPTION_FLOAT, "shadow mask texture size in U direction" }, - { WINOPTION_SHADOW_MASK_VSIZE";fs_shadwv(0.0-1.0)", "0.1875", OPTION_FLOAT, "shadow mask texture size in V direction" }, + { WINOPTION_SHADOW_MASK_COUNT_X";fs_shadww", "320", OPTION_INTEGER, "shadow mask width, in phosphor dots" }, + { WINOPTION_SHADOW_MASK_COUNT_Y";fs_shadwh", "240", OPTION_INTEGER, "shadow mask height, in phosphor dots" }, + { WINOPTION_SHADOW_MASK_USIZE";fs_shadwu(0.0-1.0)", "0.09375", OPTION_FLOAT, "shadow mask texture size in U direction" }, + { WINOPTION_SHADOW_MASK_VSIZE";fs_shadwv(0.0-1.0)", "0.109375", OPTION_FLOAT, "shadow mask texture size in V direction" }, { WINOPTION_CURVATURE";fs_curv(0.0-4.0)", "0.0", OPTION_FLOAT, "screen curvature amount" }, { WINOPTION_SCREEN_SCALE_TOP";fs_scalex(0.0-2.0)", "1.0", OPTION_FLOAT, "screen scale, top" }, { WINOPTION_SCREEN_SCALE_BOTTOM";fs_scaley(0.0-2.0)", "1.0", OPTION_FLOAT, "screen scale, bottom" }, @@ -389,9 +389,9 @@ const options_entry windows_options::s_option_entries[] = { WINOPTION_RED_SCALE";fs_redmul(0.0-2.0)", "1.0", OPTION_FLOAT, "red signal scaling value (multiplicative)" }, { WINOPTION_GREEN_SCALE";fs_grnmul(0.0-2.0)", "1.0", OPTION_FLOAT, "green signal scaling value (multiplicative)" }, { WINOPTION_BLUE_SCALE";fs_blumul(0.0-2.0)", "1.0", OPTION_FLOAT, "blue signal scaling value (multiplicative)" }, - { WINOPTION_RED_POWER";fs_redpow(0.01-32.0)", "1.0", OPTION_FLOAT, "red signal power value (exponential)" }, - { WINOPTION_GREEN_POWER";fs_grnpow(0.01-32.0)", "1.0", OPTION_FLOAT, "green signal power value (exponential)" }, - { WINOPTION_BLUE_POWER";fs_blupow(0.01-32.0)", "1.0", OPTION_FLOAT, "blue signal power value (exponential)" }, + { WINOPTION_RED_POWER";fs_redpow(0.01-4.0)", "1.0", OPTION_FLOAT, "red signal power value (exponential)" }, + { WINOPTION_GREEN_POWER";fs_grnpow(0.01-4.0)", "1.0", OPTION_FLOAT, "green signal power value (exponential)" }, + { WINOPTION_BLUE_POWER";fs_blupow(0.01-4.0)", "1.0", OPTION_FLOAT, "blue signal power value (exponential)" }, { WINOPTION_RED_FLOOR";fs_redfl(0.0-1.0)", "0.0", OPTION_FLOAT, "red signal floor level" }, { WINOPTION_GREEN_FLOOR";fs_grnfl(0.0-1.0)", "0.0", OPTION_FLOAT, "green signal floor level" }, { WINOPTION_BLUE_FLOOR";fs_blufl(0.0-1.0)", "0.0", OPTION_FLOAT, "blue signal floor level" }, @@ -405,7 +405,8 @@ const options_entry windows_options::s_option_entries[] = { WINOPTION_YIQ_BVALUE";yiqb", "0.5", OPTION_FLOAT, "B value 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_YVALUE";yiqy", "3.0", OPTION_FLOAT, "Y filter cutoff frequency 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" }, { WINOPTION_YIQ_IVALUE";yiqi", "1.2", OPTION_FLOAT, "I filter cutoff frequency for NTSC signal processing" }, { WINOPTION_YIQ_QVALUE";yiqq", "0.6", OPTION_FLOAT, "Q filter cutoff frequency for NTSC signal processing" }, { WINOPTION_YIQ_SCAN_TIME";yiqsc", "52.6", OPTION_FLOAT, "Horizontal scanline duration for NTSC signal processing (in usec)" }, diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h index fcd97c3cd68..99717cb17ca 100644 --- a/src/osd/windows/winmain.h +++ b/src/osd/windows/winmain.h @@ -147,6 +147,7 @@ #define WINOPTION_YIQ_BVALUE "yiq_b" #define WINOPTION_YIQ_OVALUE "yiq_o" #define WINOPTION_YIQ_PVALUE "yiq_p" +#define WINOPTION_YIQ_NVALUE "yiq_n" #define WINOPTION_YIQ_YVALUE "yiq_y" #define WINOPTION_YIQ_IVALUE "yiq_i" #define WINOPTION_YIQ_QVALUE "yiq_q" @@ -268,6 +269,7 @@ public: float screen_yiq_b() const { return float_value(WINOPTION_YIQ_BVALUE); } float screen_yiq_o() const { return float_value(WINOPTION_YIQ_OVALUE); } float screen_yiq_p() const { return float_value(WINOPTION_YIQ_PVALUE); } + float screen_yiq_n() const { return float_value(WINOPTION_YIQ_NVALUE); } float screen_yiq_y() const { return float_value(WINOPTION_YIQ_YVALUE); } float screen_yiq_i() const { return float_value(WINOPTION_YIQ_IVALUE); } float screen_yiq_q() const { return float_value(WINOPTION_YIQ_QVALUE); } |