From d2a29d06ab4d53e999b8bca8a4139315b7786235 Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Wed, 24 Apr 2024 04:14:52 +1000 Subject: [PATCH] Add tool for faking temporal anti-aliasing --- .../FakeTemporalAA/FakeTemporalAA.csproj | 11 +++ .../FakeTemporalAA/FakeTemporalAAToolForm.cs | 83 +++++++++++++++++++ .../FakeTemporalAA/build_debug.sh | 1 + .../FakeTemporalAA/build_release.sh | 1 + .../FakeTemporalAA/run_with_tool.sh | 1 + .../NET48ExternalToolForm.targets | 3 + 6 files changed, 100 insertions(+) create mode 100644 ExternalToolProjects/FakeTemporalAA/FakeTemporalAA.csproj create mode 100644 ExternalToolProjects/FakeTemporalAA/FakeTemporalAAToolForm.cs create mode 120000 ExternalToolProjects/FakeTemporalAA/build_debug.sh create mode 120000 ExternalToolProjects/FakeTemporalAA/build_release.sh create mode 120000 ExternalToolProjects/FakeTemporalAA/run_with_tool.sh diff --git a/ExternalToolProjects/FakeTemporalAA/FakeTemporalAA.csproj b/ExternalToolProjects/FakeTemporalAA/FakeTemporalAA.csproj new file mode 100644 index 0000000000..f61ddc82c4 --- /dev/null +++ b/ExternalToolProjects/FakeTemporalAA/FakeTemporalAA.csproj @@ -0,0 +1,11 @@ + + + + + true + $(NoWarn);IDE0065;SA1200 + + + + + diff --git a/ExternalToolProjects/FakeTemporalAA/FakeTemporalAAToolForm.cs b/ExternalToolProjects/FakeTemporalAA/FakeTemporalAAToolForm.cs new file mode 100644 index 0000000000..d6720cc94f --- /dev/null +++ b/ExternalToolProjects/FakeTemporalAA/FakeTemporalAAToolForm.cs @@ -0,0 +1,83 @@ +namespace BizHawk.Experiments.FakeTemporalAA; + +using System; + +using BizHawk.Bizware.Graphics; +using BizHawk.Client.Common; +using BizHawk.Client.EmuHawk; +using BizHawk.Emulation.Common; + +[ExternalTool(TOOL_NAME, Description = "Naively blends each frame with the previous")] +public sealed class FakeTemporalAAToolForm: ToolFormBase, IExternalToolForm +{ + private const string TOOL_NAME = "Fake Temporal Anti-aliasing"; + + private BitmapBuffer? _bbPrev = null; + + [RequiredService] + public IVideoProvider? _maybeVideoProvider { get; set; } + + public ApiContainer? _maybeAPIContainer { get; set; } + + private ApiContainer APIs + => _maybeAPIContainer!; + + protected override string WindowTitleStatic + => TOOL_NAME; + + public FakeTemporalAAToolForm() + => _ = _maybeVideoProvider; // used via ToolFormBase.MainForm + + private void ClearDrawingSurface() + => APIs.Gui.WithSurface(DisplaySurfaceID.EmuCore, g => g.ClearGraphics(DisplaySurfaceID.EmuCore)); + + protected override void Dispose(bool disposing) + { + ClearDrawingSurface(); + base.Dispose(disposing); + } + + public override void Restart() + { + _bbPrev = null; + ClearDrawingSurface(); + } + + public override void UpdateValues(ToolFormUpdateType type) + { + const int OPACITY_MASK = 0xFF << 24; + static void Invert(Span buf) + { + for (var i = 0; i < buf.Length; i++) buf[i] = OPACITY_MASK | ~buf[i]; //TODO vectorise? + } + static int AverageXRGB(int c1, int c2) + { + //TODO can this be improved? + const int R_MASK = 0xFF0000; + const int G_MASK = 0xFF00; + const int B_MASK = 0xFF; + var r = (((c1 & R_MASK) + (c2 & R_MASK)) / 2) & R_MASK; + var g = (((c1 & G_MASK) + (c2 & G_MASK)) / 2) & G_MASK; + var b = (((c1 & B_MASK) + (c2 & B_MASK)) / 2) & B_MASK; + var c3 = r | g | b; + c3 &= ~OPACITY_MASK; + return OPACITY_MASK | c3; + } + if (type is not (ToolFormUpdateType.PreFrame or ToolFormUpdateType.FastPreFrame)) return; + + var bbCurrent = MainForm.MakeScreenshotImage(); + var spanCurrent = bbCurrent.AsSpan(); + Invert(spanCurrent); + if (_bbPrev is null) // initialisation + { + _bbPrev = bbCurrent; + return; + } + + var spanPrev = _bbPrev.AsSpan(); // was inverted before saving + for (var i = 0; i < spanCurrent.Length; i++) spanPrev[i] = AverageXRGB(spanPrev[i], spanCurrent[i]); + Invert(spanPrev); + APIs.Gui.WithSurface(DisplaySurfaceID.EmuCore, g => g.DrawImage(_bbPrev!.ToSysdrawingBitmap(), 0, 0, cache: false)); + _bbPrev = bbCurrent; + } +} diff --git a/ExternalToolProjects/FakeTemporalAA/build_debug.sh b/ExternalToolProjects/FakeTemporalAA/build_debug.sh new file mode 120000 index 0000000000..c2127aded1 --- /dev/null +++ b/ExternalToolProjects/FakeTemporalAA/build_debug.sh @@ -0,0 +1 @@ +../.build_debug.sh \ No newline at end of file diff --git a/ExternalToolProjects/FakeTemporalAA/build_release.sh b/ExternalToolProjects/FakeTemporalAA/build_release.sh new file mode 120000 index 0000000000..801b8e5998 --- /dev/null +++ b/ExternalToolProjects/FakeTemporalAA/build_release.sh @@ -0,0 +1 @@ +../.build_release.sh \ No newline at end of file diff --git a/ExternalToolProjects/FakeTemporalAA/run_with_tool.sh b/ExternalToolProjects/FakeTemporalAA/run_with_tool.sh new file mode 120000 index 0000000000..b7cf6138ab --- /dev/null +++ b/ExternalToolProjects/FakeTemporalAA/run_with_tool.sh @@ -0,0 +1 @@ +../.run_with_tool.sh \ No newline at end of file diff --git a/ExternalToolProjects/NET48ExternalToolForm.targets b/ExternalToolProjects/NET48ExternalToolForm.targets index f65ba71ec9..822130c2c6 100644 --- a/ExternalToolProjects/NET48ExternalToolForm.targets +++ b/ExternalToolProjects/NET48ExternalToolForm.targets @@ -8,6 +8,9 @@ +