diff --git a/hlsl/ghosting.fx b/hlsl/ghosting.fx new file mode 100644 index 00000000000..f09bab41fba --- /dev/null +++ b/hlsl/ghosting.fx @@ -0,0 +1,159 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz, Westley M. Martinez +//----------------------------------------------------------------------------- +// Ghosting Effect +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Sampler Definitions +//----------------------------------------------------------------------------- + +texture Diffuse; + +sampler DiffuseSampler = sampler_state +{ + Texture = ; + SRGBTexture = TRUE; + MipFilter = LINEAR; + MinFilter = LINEAR; + MagFilter = LINEAR; + AddressU = CLAMP; + AddressV = CLAMP; + AddressW = CLAMP; +}; + +texture LastPass; + +sampler PreviousSampler = sampler_state +{ + Texture = ; + SRGBTexture = TRUE; + 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; + float2 PrevCoord : TEXCOORD1; +}; + +struct VS_INPUT +{ + float3 Position : POSITION; + float4 Color : COLOR0; + float2 TexCoord : TEXCOORD0; +}; + +struct PS_INPUT +{ + float4 Color : COLOR0; + float2 TexCoord : TEXCOORD0; + float2 PrevCoord : TEXCOORD1; +}; + +//----------------------------------------------------------------------------- +// Phosphor Vertex Shader +//----------------------------------------------------------------------------- + +uniform float2 ScreenDims; +uniform float2 TargetDims; + +uniform bool Passthrough; + +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 / TargetDims; // half texel offset correction (DX9) + + Output.PrevCoord = Output.TexCoord; + + Output.Color = Input.Color; + + return Output; +} + +//----------------------------------------------------------------------------- +// Phosphor Pixel Shader +//----------------------------------------------------------------------------- + +uniform float DeltaTime = 0.0f; +uniform float3 LCDRise = { 0.0f, 0.0f, 0.0f }; +uniform float3 LCDFall = { 0.0f, 0.0f, 0.0f }; +static const float TAU_FACTOR = 0.159154943; + +float4 ps_main(PS_INPUT Input) : COLOR +{ + float4 CurrPix = tex2D(DiffuseSampler, Input.TexCoord); + float3 PrevPix = tex2D(PreviousSampler, Input.PrevCoord).rgb; + float3 tau = { 0.0f, 0.0f, 0.0f }; + float r = PrevPix.r; + float g = PrevPix.g; + float b = PrevPix.b; + + if (CurrPix.r > r) { + tau.r = LCDRise.r * TAU_FACTOR; + r = tau.r == 0 ? CurrPix.r : (CurrPix.r - r) * + (1 - exp(-DeltaTime / tau.r)) + r; + } + else { + tau.r = LCDFall.r * TAU_FACTOR; + r = tau.r == 0 ? CurrPix.r : (r - CurrPix.r) * + exp(-DeltaTime / tau.r) + CurrPix.r; + } + if (CurrPix.g > g) { + tau.g = LCDRise.g * TAU_FACTOR; + g = tau.g == 0 ? CurrPix.g : (CurrPix.g - g) * + (1 - exp(-DeltaTime / tau.g)) + g; + } + else { + tau.g = LCDFall.g * TAU_FACTOR; + g = tau.g == 0 ? CurrPix.g : (g - CurrPix.g) * + exp(-DeltaTime / tau.g) + CurrPix.g; + } + if (CurrPix.b > b) { + tau.b = LCDRise.b * TAU_FACTOR; + b = tau.b == 0 ? CurrPix.b : (CurrPix.b - b) * + (1 - exp(-DeltaTime / tau.b)) + b; + } + else { + tau.b = LCDFall.b * TAU_FACTOR; + b = tau.b == 0 ? CurrPix.b : (b - CurrPix.b) * + exp(-DeltaTime / tau.b) + CurrPix.b; + } + return Passthrough ? CurrPix : float4(r, g, b, CurrPix.a); +} + +//----------------------------------------------------------------------------- +// Phosphor Technique +//----------------------------------------------------------------------------- + +technique DefaultTechnique +{ + pass Pass0 + { + SRGBWriteEnable = TRUE; + Lighting = FALSE; + + VertexShader = compile vs_2_0 vs_main(); + PixelShader = compile ps_2_0 ps_main(); + } +} diff --git a/hlsl/phosphor.fx b/hlsl/phosphor.fx index 579a110eb6d..2505b27e17f 100644 --- a/hlsl/phosphor.fx +++ b/hlsl/phosphor.fx @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Ryan Holtz +// copyright-holders:Ryan Holtz, Westley M. Martinez //----------------------------------------------------------------------------- // Phosphor Effect //----------------------------------------------------------------------------- @@ -95,12 +95,14 @@ VS_OUTPUT vs_main(VS_INPUT Input) // Phosphor Pixel Shader //----------------------------------------------------------------------------- -uniform bool LCD = false; uniform int Mode = 0; uniform float DeltaTime = 0.0f; -uniform float LCDTau = 0.0f; uniform float3 TimeConstant = { 0.0f, 0.0f, 0.0f }; uniform float3 Beta = { 0.0f, 0.0f, 0.0f }; +static const float TAU_FACTOR = 0.4342944819; +static const float GAMMA_INV_FACTOR = TAU_FACTOR / 100; +// sRGB half-step for small intensities +float THRESHOLD = 0.5f / 255.0f / 12.92f; float4 ps_main(PS_INPUT Input) : COLOR { @@ -110,47 +112,41 @@ float4 ps_main(PS_INPUT Input) : COLOR float g = PrevPix.g; float b = PrevPix.b; - if (LCD) { - r *= LCDTau == 0 ? 0 : exp(-DeltaTime / LCDTau); - g *= LCDTau == 0 ? 0 : exp(-DeltaTime / LCDTau); - b *= LCDTau == 0 ? 0 : exp(-DeltaTime / LCDTau); - } - else if (Mode == 0) { + if (Mode == 0) { r = 0; g = 0; b = 0; } else if (Mode == 1) { - float3 tau = TimeConstant * 0.4342944819; + float3 tau = TimeConstant * TAU_FACTOR; r *= tau.r == 0 ? 0 : exp(-DeltaTime / tau.r); g *= tau.g == 0 ? 0 : exp(-DeltaTime / tau.g); b *= tau.b == 0 ? 0 : exp(-DeltaTime / tau.b); } else { - float3 gamma = 1 / (TimeConstant * 0.004342944819); + float3 gamma = 1 / (TimeConstant * GAMMA_INV_FACTOR); if (r != 0.0f) - r = pow(gamma.r * DeltaTime + pow(1 / r, 1 / Beta.r), -Beta.r); + r = pow(gamma.r * DeltaTime + pow(1 / r, 1 / Beta.r), + -Beta.r); if (g != 0.0f) - g = pow(gamma.g * DeltaTime + pow(1 / g, 1 / Beta.g), -Beta.g); + g = pow(gamma.g * DeltaTime + pow(1 / g, 1 / Beta.g), + -Beta.g); if (b != 0.0f) - b = pow(gamma.b * DeltaTime + pow(1 / b, 1 / Beta.b), -Beta.b); + b = pow(gamma.b * DeltaTime + pow(1 / b, 1 / Beta.b), + -Beta.b); } // Prevent burn-in if (DeltaTime > 0.0f) { - float threshold = 0.5f / 255.0f / 12.92; // Half-color increment - r = max(0.0f, r - threshold); - g = max(0.0f, g - threshold); - b = max(0.0f, b - threshold); + r = max(0.0f, r - THRESHOLD); + g = max(0.0f, g - THRESHOLD); + b = max(0.0f, b - THRESHOLD); } - - float RedMax = max(CurrPix.r, r); - float GreenMax = max(CurrPix.g, g); - float BlueMax = max(CurrPix.b, b); - - return Passthrough ? - CurrPix : float4(RedMax, GreenMax, BlueMax, CurrPix.a); + r = max(CurrPix.r, r); + g = max(CurrPix.g, g); + b = max(CurrPix.b, b); + return Passthrough ? CurrPix : float4(r, g, b, CurrPix.a); } //----------------------------------------------------------------------------- diff --git a/ini/presets/gameboy.ini b/ini/presets/gameboy.ini index a95ef2a453c..3ac98f98ee0 100644 --- a/ini/presets/gameboy.ini +++ b/ini/presets/gameboy.ini @@ -31,7 +31,8 @@ offset 0.0,0.10,0.05 scale 0.9,0.8,1.0 power 1.4,1.2,1.8 floor 0.0,0.0,0.0 -lcd_persistence 0.04 +lcd_rise_time 0.25,0.25,0.25 +lcd_fall_time 0.1,0.1,0.1 # # NTSC POST-PROCESSING OPTIONS diff --git a/ini/presets/gba.ini b/ini/presets/gba.ini index c39a627099e..1be2a736d4e 100644 --- a/ini/presets/gba.ini +++ b/ini/presets/gba.ini @@ -31,7 +31,8 @@ offset 0.0,0.0,0.0 scale 1.0,1.0,1.0 power 1.0,1.0,1.0 floor 0.0,0.0,0.0 -lcd_persistence 0.03,0.03,0.03 +lcd_rise_time 0.05,0.05,0.05 +lcd_fall_time 0.1,0.1,0.1 # # NTSC POST-PROCESSING OPTIONS diff --git a/ini/presets/lcd-matrix.ini b/ini/presets/lcd-matrix.ini index 7728e1cf281..7103ae5bc8f 100644 --- a/ini/presets/lcd-matrix.ini +++ b/ini/presets/lcd-matrix.ini @@ -31,7 +31,8 @@ offset 0.0,0.0,0.0 scale 1.0,1.0,1.0 power 1.0,1.0,1.0 floor 0.0,0.0,0.0 -lcd_persistence 0.03,0.03,0.03 +lcd_rise_time 0.25,0.25,0.25 +lcd_fall_time 0.1,0.1,0.1 # # NTSC POST-PROCESSING OPTIONS diff --git a/ini/presets/lcd.ini b/ini/presets/lcd.ini index c39a627099e..1be2a736d4e 100644 --- a/ini/presets/lcd.ini +++ b/ini/presets/lcd.ini @@ -31,7 +31,8 @@ offset 0.0,0.0,0.0 scale 1.0,1.0,1.0 power 1.0,1.0,1.0 floor 0.0,0.0,0.0 -lcd_persistence 0.03,0.03,0.03 +lcd_rise_time 0.05,0.05,0.05 +lcd_fall_time 0.1,0.1,0.1 # # NTSC POST-PROCESSING OPTIONS diff --git a/ini/presets/raster.ini b/ini/presets/raster.ini index 702f071060b..c566fbe15ff 100644 --- a/ini/presets/raster.ini +++ b/ini/presets/raster.ini @@ -38,8 +38,8 @@ scale 1.15,1.05,0.90 power 0.90,0.90,1.15 floor 0.025,0.025,0.025 phosphor_mode 2 -phosphor_time 0.050,0.005,0.005 -phosphor_beta 1.0,0.5,0.5 +phosphor_time 0.050,0.018,0.018 +phosphor_beta 1.0,0.7,0.7 # # NTSC POST-PROCESSING OPTIONS diff --git a/ini/presets/vector.ini b/ini/presets/vector.ini index c1b57de84a9..c2d41cf5cb6 100644 --- a/ini/presets/vector.ini +++ b/ini/presets/vector.ini @@ -41,8 +41,8 @@ scale 1.0,1.0,1.0 power 1.0,1.0,1.0 floor 0.0,0.0,0.0 phosphor_mode 2 -phosphor_time 0.050,0.005,0.005 -phosphor_beta 1.0,0.5,0.5 +phosphor_time 0.050,0.018,0.018 +phosphor_beta 1.0,0.7,0.7 # # NTSC POST-PROCESSING OPTIONS diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp index 1e0f42a7bd8..9ae9521a3a7 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.cpp +++ b/src/osd/modules/render/d3d/d3dhlsl.cpp @@ -1,5 +1,4 @@ // license:BSD-3-Clause -// // copyright-holders:Aaron Giles //============================================================ // @@ -170,9 +169,9 @@ shaders::shaders() : snap_copy_target(nullptr), snap_copy_texture(nullptr), snap_target(nullptr), snap_texture(nullptr), snap_width(0), snap_height(0), initialized(false), backbuffer(nullptr), curr_effect(nullptr), default_effect(nullptr), prescale_effect(nullptr), post_effect(nullptr), distortion_effect(nullptr), - focus_effect(nullptr), phosphor_effect(nullptr), deconverge_effect(nullptr), color_effect(nullptr), - ntsc_effect(nullptr), bloom_effect(nullptr), downsample_effect(nullptr), vector_effect(nullptr), - curr_texture(nullptr), curr_render_target(nullptr), curr_poly(nullptr), + focus_effect(nullptr), phosphor_effect(nullptr), ghosting_effect(nullptr), deconverge_effect(nullptr), + color_effect(nullptr), ntsc_effect(nullptr), bloom_effect(nullptr), downsample_effect(nullptr), + vector_effect(nullptr), curr_texture(nullptr), curr_render_target(nullptr), curr_poly(nullptr), d3dx_create_effect_from_file_ptr(nullptr) { } @@ -524,7 +523,10 @@ bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r options->phosphor_time, true); get_vector(winoptions.screen_phosphor_beta(), 3, options->phosphor_beta, true); - options->lcd_persistence = winoptions.screen_lcd_persistence(); + get_vector(winoptions.screen_lcd_rise_time(), 3, + options->lcd_rise_time, true); + get_vector(winoptions.screen_lcd_fall_time(), 3, + options->lcd_fall_time, true); options->saturation = winoptions.screen_saturation(); options->yiq_enable = winoptions.screen_yiq_enable(); options->yiq_jitter = winoptions.screen_yiq_jitter(); @@ -715,6 +717,7 @@ int shaders::create_resources() distortion_effect = new effect(this, d3d->get_device(), "distortion.fx", fx_dir); prescale_effect = new effect(this, d3d->get_device(), "prescale.fx", fx_dir); phosphor_effect = new effect(this, d3d->get_device(), "phosphor.fx", fx_dir); + ghosting_effect = new effect(this, d3d->get_device(), "ghosting.fx", fx_dir); 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); @@ -728,6 +731,7 @@ int shaders::create_resources() !distortion_effect->is_valid() || !prescale_effect->is_valid() || !phosphor_effect->is_valid() || + !ghosting_effect->is_valid() || !focus_effect->is_valid() || !deconverge_effect->is_valid() || !color_effect->is_valid() || @@ -739,12 +743,13 @@ int shaders::create_resources() return 1; } - effect *effects[13] = { + effect *effects[14] = { default_effect, post_effect, distortion_effect, prescale_effect, phosphor_effect, + ghosting_effect, focus_effect, deconverge_effect, color_effect, @@ -755,7 +760,7 @@ int shaders::create_resources() vector_effect }; - for (int i = 0; i < 13; i++) + for (int i = 0; i < 14; i++) { effects[i]->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); effects[i]->add_uniform("TargetDims", uniform::UT_VEC2, uniform::CU_TARGET_DIMS); @@ -795,7 +800,9 @@ int shaders::create_resources() phosphor_effect->add_uniform("Mode", uniform::UT_INT, uniform::CU_PHOSPHOR_MODE); phosphor_effect->add_uniform("TimeConstant", uniform::UT_VEC3, uniform::CU_PHOSPHOR_TIME); phosphor_effect->add_uniform("Beta", uniform::UT_VEC3, uniform::CU_PHOSPHOR_BETA); - phosphor_effect->add_uniform("LCDTau", uniform::UT_FLOAT, uniform::CU_LCD_PERSISTENCE); + + ghosting_effect->add_uniform("LCDRise", uniform::UT_FLOAT, uniform::CU_LCD_RISE_TIME); + ghosting_effect->add_uniform("LCDFall", uniform::UT_FLOAT, uniform::CU_LCD_FALL_TIME); post_effect->add_uniform("ShadowAlpha", uniform::UT_FLOAT, uniform::CU_POST_SHADOW_ALPHA); post_effect->add_uniform("ShadowCount", uniform::UT_VEC2, uniform::CU_POST_SHADOW_COUNT); @@ -848,6 +855,7 @@ void shaders::begin_draw() distortion_effect->set_technique("DefaultTechnique"); prescale_effect->set_technique("DefaultTechnique"); phosphor_effect->set_technique("DefaultTechnique"); + ghosting_effect->set_technique("DefaultTechnique"); focus_effect->set_technique("DefaultTechnique"); deconverge_effect->set_technique("DefaultTechnique"); color_effect->set_technique("DefaultTechnique"); @@ -1079,10 +1087,9 @@ int shaders::phosphor_pass(d3d_render_target *rt, int source_index, poly_info *p int next_index = source_index; auto stype = machine->first_screen()->screen_type(); - // skip phosphor if mode is off - if ((options->phosphor_mode == 0 && stype == SCREEN_TYPE_RASTER) || - (options->phosphor_mode == 0 && stype == SCREEN_TYPE_VECTOR) || - (options->lcd_persistence == 0 && stype == SCREEN_TYPE_LCD)) + // skip if screen doesn't use phosphors + if ((stype != SCREEN_TYPE_RASTER && stype != SCREEN_TYPE_VECTOR) || + options->phosphor_mode == 0) { return next_index; } @@ -1093,10 +1100,6 @@ int shaders::phosphor_pass(d3d_render_target *rt, int source_index, poly_info *p curr_effect->set_texture("LastPass", rt->cache_texture); curr_effect->set_bool("Passthrough", false); curr_effect->set_float("DeltaTime", delta_time()); - if (stype == SCREEN_TYPE_LCD) - curr_effect->set_bool("LCD", true); - else - curr_effect->set_bool("LCD", false); next_index = rt->next_index(next_index); blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); @@ -1112,6 +1115,38 @@ int shaders::phosphor_pass(d3d_render_target *rt, int source_index, poly_info *p return next_index; } +int shaders::ghosting_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum) +{ + int next_index = source_index; + auto stype = machine->first_screen()->screen_type(); + + if (stype != SCREEN_TYPE_LCD || + (options->lcd_rise_time == 0 && options->lcd_fall_time == 0)) + { + return next_index; + } + + curr_effect = ghosting_effect; + curr_effect->update_uniforms(); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); + curr_effect->set_texture("LastPass", rt->cache_texture); + curr_effect->set_bool("Passthrough", false); + curr_effect->set_float("DeltaTime", delta_time()); + + next_index = rt->next_index(next_index); + blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + + // Pass along our ghost'd screen + curr_effect->update_uniforms(); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); + curr_effect->set_texture("LastPass", rt->target_texture[next_index]); + curr_effect->set_bool("Passthrough", true); + + blit(rt->cache_surface, false, D3DPT_TRIANGLELIST, 0, 2); + + return next_index; +} + int shaders::post_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum, bool prepare_bloom) { int next_index = source_index; @@ -1379,8 +1414,10 @@ void shaders::render_quad(poly_info *poly, int vertnum) next_index = deconverge_pass(rt, next_index, poly, vertnum); // handled in bgfx next_index = defocus_pass(rt, next_index, poly, vertnum); next_index = phosphor_pass(rt, next_index, poly, vertnum); + next_index = ghosting_pass(rt, next_index, poly, vertnum); // create bloom textures + // This may be phosphor or ghosting, depending on screen type int phosphor_index = next_index; next_index = post_pass(rt, next_index, poly, vertnum, true); next_index = downsample_pass(rt, next_index, poly, vertnum); @@ -1458,8 +1495,10 @@ void shaders::render_quad(poly_info *poly, int vertnum) next_index = deconverge_pass(rt, next_index, poly, vertnum); next_index = defocus_pass(rt, next_index, poly, vertnum); next_index = phosphor_pass(rt, next_index, poly, vertnum); + next_index = ghosting_pass(rt, next_index, poly, vertnum); // create bloom textures + // This may be phosphor or ghosting, depending on screen type int phosphor_index = next_index; next_index = post_pass(rt, next_index, poly, vertnum, true); next_index = downsample_pass(rt, next_index, poly, vertnum); @@ -1750,6 +1789,11 @@ void shaders::delete_resources() delete phosphor_effect; phosphor_effect = nullptr; } + if (ghosting_effect != nullptr) + { + delete ghosting_effect; + ghosting_effect = nullptr; + } if (focus_effect != nullptr) { delete focus_effect; @@ -1967,7 +2011,8 @@ enum slider_option SLIDER_PHOSPHOR_MODE, SLIDER_PHOSPHOR_TIME, SLIDER_PHOSPHOR_BETA, - SLIDER_LCD_PERSISTENCE, + SLIDER_LCD_RISE_TIME, + SLIDER_LCD_FALL_TIME, SLIDER_BLOOM_BLEND_MODE, SLIDER_BLOOM_SCALE, SLIDER_BLOOM_OVERDRIVE, @@ -2049,7 +2094,8 @@ slider_desc shaders::s_sliders[] = { "Phosphor Persistence Mode,", 0, 0, 2, 1, SLIDER_INT_ENUM, SLIDER_SCREEN_TYPE_RASTER_OR_VECTOR, SLIDER_PHOSPHOR_MODE, 0, "%s", { "Off", "Exponential", "Inverse Power" } }, { "Phosphor Persistence Time Constant,",1, 5000, 10000,10, SLIDER_COLOR, SLIDER_SCREEN_TYPE_RASTER_OR_VECTOR, SLIDER_PHOSPHOR_TIME, 0.0001f, "%4.4f", {} }, { "Phosphor Persistence beta,", 50, 100, 200, 1, SLIDER_COLOR, SLIDER_SCREEN_TYPE_RASTER_OR_VECTOR, SLIDER_PHOSPHOR_BETA, 0.01f, "%2.2f", {} }, - { "LCD Perisistence,", 0, 20, 100, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD, SLIDER_LCD_PERSISTENCE, 0.001f, "%3.3f", {} }, + { "LCD Rise Time Constant,", 0, 50, 100, 1, SLIDER_COLOR, SLIDER_SCREEN_TYPE_LCD, SLIDER_LCD_RISE_TIME, 0.01f, "%2.2f", {} }, + { "LCD Fall Time Constant,", 0, 50, 100, 1, SLIDER_COLOR, SLIDER_SCREEN_TYPE_LCD, SLIDER_LCD_FALL_TIME, 0.01f, "%2.2f", {} }, { "Bloom Blend Mode", 0, 0, 1, 1, SLIDER_INT_ENUM, SLIDER_SCREEN_TYPE_ANY, SLIDER_BLOOM_BLEND_MODE, 0, "%s", { "Brighten", "Darken" } }, { "Bloom Scale", 0, 0, 2000, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_ANY, SLIDER_BLOOM_SCALE, 0.001f, "%1.3f", {} }, { "Bloom Overdrive,", 0, 0, 2000, 5, SLIDER_COLOR, SLIDER_SCREEN_TYPE_ANY, SLIDER_BLOOM_OVERDRIVE, 0.001f, "%1.3f", {} }, @@ -2124,7 +2170,8 @@ void *shaders::get_slider_option(int id, int index) case SLIDER_PHOSPHOR_MODE: return &(options->phosphor_mode); case SLIDER_PHOSPHOR_TIME: return &(options->phosphor_time[index]); case SLIDER_PHOSPHOR_BETA: return &(options->phosphor_beta[index]); - case SLIDER_LCD_PERSISTENCE: return &(options->lcd_persistence); + case SLIDER_LCD_RISE_TIME: return &(options->lcd_rise_time[index]); + case SLIDER_LCD_FALL_TIME: return &(options->lcd_fall_time[index]); case SLIDER_BLOOM_BLEND_MODE: return &(options->bloom_blend_mode); case SLIDER_BLOOM_SCALE: return &(options->bloom_scale); case SLIDER_BLOOM_OVERDRIVE: return &(options->bloom_overdrive[index]); @@ -2421,8 +2468,12 @@ void uniform::update() m_shader->set_vector("Beta", 3, options->phosphor_beta); break; - case CU_LCD_PERSISTENCE: - m_shader->set_float("LCDTau", options->lcd_persistence); + case CU_LCD_RISE_TIME: + m_shader->set_vector("LCDRise", 3, options->lcd_rise_time); + break; + case CU_LCD_FALL_TIME: + m_shader->set_vector("LCDFall", 3, options->lcd_fall_time); + break; case CU_POST_REFLECTION: m_shader->set_float("ReflectionAmount", options->reflection); diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h index fd31e2fe679..6c94be09793 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.h +++ b/src/osd/modules/render/d3d/d3dhlsl.h @@ -81,7 +81,8 @@ public: CU_PHOSPHOR_TIME, CU_PHOSPHOR_BETA, - CU_LCD_PERSISTENCE, + CU_LCD_RISE_TIME, + CU_LCD_FALL_TIME, CU_POST_VIGNETTING, CU_POST_DISTORTION, @@ -210,7 +211,8 @@ struct hlsl_options int phosphor_mode; float phosphor_time[3]; float phosphor_beta[3]; - float lcd_persistence; + float lcd_rise_time[3]; + float lcd_fall_time[3]; float saturation; // NTSC @@ -339,6 +341,7 @@ private: int deconverge_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum); int defocus_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum); int phosphor_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum); + int ghosting_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum); int post_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum, bool prepare_bloom); int downsample_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum); int bloom_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum); @@ -388,6 +391,7 @@ private: effect * distortion_effect; // pointer to the distortion-effect object effect * focus_effect; // pointer to the focus-effect object effect * phosphor_effect; // pointer to the phosphor-effect object + effect * ghosting_effect; // pointer te the LCD ghosting effect object effect * deconverge_effect; // pointer to the deconvergence-effect object effect * color_effect; // pointer to the color-effect object effect * ntsc_effect; // pointer to the NTSC effect object diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp index 70a2a467ae6..505d764b17c 100644 --- a/src/osd/windows/winmain.cpp +++ b/src/osd/windows/winmain.cpp @@ -216,9 +216,10 @@ const options_entry windows_options::s_option_entries[] = { WINOPTION_POWER";fs_power", "1.0,1.0,1.0", OPTION_STRING, "signal power value (exponential)" }, { WINOPTION_FLOOR";fs_floor", "0.0,0.0,0.0", OPTION_STRING, "signal floor level" }, { WINOPTION_PHOSPHOR_MODE";fs_phosphor_mode", "0", OPTION_STRING, "phosphorescence decay mode (0: off, 1: exponential, 2: inverse-power)" }, - { WINOPTION_PHOSPHOR_TIME";fs_phosphor_time", "0.5,0.5,0.5", OPTION_STRING, "exponential time constant" }, + { WINOPTION_PHOSPHOR_TIME";fs_phosphor_time", "0.5,0.5,0.5", OPTION_STRING, "exponential time constant" }, { WINOPTION_PHOSPHOR_BETA";fs_phosphor_beta", "1.0,1.0,1.0", OPTION_STRING, "inverse power order" }, - { WINOPTION_LCD_PERSISTENCE";fs_lcd_persistence", "0.02", OPTION_STRING, "LCD pixel persistence time constant" }, + { WINOPTION_LCD_RISE_TIME";fs_lcd_rise_time", "0.0,0.0,0.0", OPTION_STRING, "LCD persistence rise time constant" }, + { WINOPTION_LCD_FALL_TIME";fs_lcd_fall_time", "0.5,0.5,0.5", OPTION_STRING, "LCD persistence fall time constant" }, /* NTSC simulation below this line */ { nullptr, nullptr, OPTION_HEADER, "NTSC POST-PROCESSING OPTIONS" }, { WINOPTION_YIQ_ENABLE";yiq", "0", OPTION_BOOLEAN, "enables YIQ-space HLSL post-processing" }, diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h index e613b32d26f..c9391aeb75d 100644 --- a/src/osd/windows/winmain.h +++ b/src/osd/windows/winmain.h @@ -71,7 +71,8 @@ #define WINOPTION_PHOSPHOR_MODE "phosphor_mode" #define WINOPTION_PHOSPHOR_TIME "phosphor_time" #define WINOPTION_PHOSPHOR_BETA "phosphor_beta" -#define WINOPTION_LCD_PERSISTENCE "lcd_persistence" +#define WINOPTION_LCD_RISE_TIME "lcd_rise_time" +#define WINOPTION_LCD_FALL_TIME "lcd_fall_time" #define WINOPTION_SATURATION "saturation" #define WINOPTION_YIQ_ENABLE "yiq_enable" #define WINOPTION_YIQ_JITTER "yiq_jitter" @@ -203,7 +204,8 @@ public: int screen_phosphor_mode() const { return int_value(WINOPTION_PHOSPHOR_MODE); } const char* screen_phosphor_time() const { return value(WINOPTION_PHOSPHOR_TIME); } const char* screen_phosphor_beta() const { return value(WINOPTION_PHOSPHOR_BETA); } - float screen_lcd_persistence() const { return float_value(WINOPTION_LCD_PERSISTENCE); } + const char* screen_lcd_rise_time() const { return value(WINOPTION_LCD_RISE_TIME); } + const char* screen_lcd_fall_time() const { return value(WINOPTION_LCD_FALL_TIME); } float screen_saturation() const { return float_value(WINOPTION_SATURATION); } // full screen options