diff --git a/fluXis.Desktop/Integration/SteamManager.cs b/fluXis.Desktop/Integration/SteamManager.cs index d70c6caff..42e21b47e 100644 --- a/fluXis.Desktop/Integration/SteamManager.cs +++ b/fluXis.Desktop/Integration/SteamManager.cs @@ -264,5 +264,6 @@ protected override void Dispose(bool isDisposing) ticketCb?.Dispose(); createItemCb?.Dispose(); submitItemCb?.Dispose(); + keyboardClose?.Dispose(); } } diff --git a/fluXis.Resources/Shaders/sh_BlurCompose.fs b/fluXis.Resources/Shaders/sh_BlurCompose.fs new file mode 100644 index 000000000..f28e47dfd --- /dev/null +++ b/fluXis.Resources/Shaders/sh_BlurCompose.fs @@ -0,0 +1,20 @@ +layout(set = 0, binding = 0) uniform texture2D u_Original; +layout(set = 0, binding = 1) uniform sampler s_Original; + +layout(set = 1, binding = 0) uniform texture2D u_Blurred; +layout(set = 1, binding = 1) uniform sampler s_Blurred; + +layout(set = 2, binding = 0) uniform m_BlurComposeParameters +{ + float g_Strength; +}; + +layout(location = 2) in vec2 v_TexCoord; +layout(location = 0) out vec4 o_Colour; + +void main() +{ + vec3 scene = texture(sampler2D(u_Original, s_Original), v_TexCoord).rgb; + vec3 blur = texture(sampler2D(u_Blurred, s_Blurred), v_TexCoord).rgb; + o_Colour = vec4(scene + blur * g_Strength, 1.0); +} \ No newline at end of file diff --git a/fluXis.Tests/Graphics/TestShaderStackContainer.cs b/fluXis.Tests/Graphics/TestShaderStackContainer.cs index d1b9925f4..c4b146095 100644 --- a/fluXis.Tests/Graphics/TestShaderStackContainer.cs +++ b/fluXis.Tests/Graphics/TestShaderStackContainer.cs @@ -1,19 +1,15 @@ +using System; using System.Collections.Generic; using fluXis.Graphics.Background; using fluXis.Graphics.Shaders; -using fluXis.Graphics.Shaders.Chromatic; -using fluXis.Graphics.Shaders.Greyscale; -using fluXis.Graphics.Shaders.Invert; -using fluXis.Graphics.Shaders.Mosaic; -using fluXis.Graphics.Shaders.Noise; -using fluXis.Graphics.Shaders.Retro; -using fluXis.Graphics.Shaders.Vignette; using fluXis.Map; +using fluXis.Map.Structures.Events; using fluXis.Mods; using fluXis.Replays; using fluXis.Screens; using fluXis.Screens.Gameplay; using fluXis.Screens.Gameplay.Replays; +using fluXis.Utils.Attributes; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -39,7 +35,7 @@ private void load(MapStore maps) var stack = new ShaderStackContainer { RelativeSizeAxes = Axes.Both }; - var chroma = new ChromaticContainer { RelativeSizeAxes = Axes.Both }; + /*var chroma = new ChromaticContainer { RelativeSizeAxes = Axes.Both }; stack.AddShader(chroma); AddSliderStep("Chroma Strength", 0, 20, 0, strength => chroma.Strength = strength); @@ -65,7 +61,38 @@ private void load(MapStore maps) var retro = new RetroContainer { RelativeSizeAxes = Axes.Both }; stack.AddShader(retro); - AddSliderStep("Retro Strength", 0, 1f, 0f, strength => retro.Strength = strength); + AddSliderStep("Retro Strength", 0, 1f, 0f, strength => retro.Strength = strength);*/ + + foreach (var shaderType in Enum.GetValues()) + { + var shd = ShaderStackContainer.CreateForType(shaderType); + if (shd is null) continue; + + stack.AddShader(shd); + + var attrs = shd.Type.TryGetAllAttributes(out var a) ? a : [new ShaderStrengthAttribute()]; + + foreach (var attr in attrs) + { + AddSliderStep($"{shaderType.ToString()} Strength {attr.Index}", attr.Min, attr.Max, 0, strength => + { + switch (attr.Index) + { + case 1: + shd.Strength = strength; + break; + + case 2: + shd.Strength2 = strength; + break; + + case 3: + shd.Strength3 = strength; + break; + } + }); + } + } stack.AddContent(new Drawable[] { diff --git a/fluXis/Graphics/Shaders/Bloom/BloomContainer.cs b/fluXis/Graphics/Shaders/Bloom/BloomContainer.cs deleted file mode 100644 index dc24b1eb5..000000000 --- a/fluXis/Graphics/Shaders/Bloom/BloomContainer.cs +++ /dev/null @@ -1,31 +0,0 @@ -using fluXis.Configuration; -using fluXis.Map.Structures.Events; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; - -namespace fluXis.Graphics.Shaders.Bloom; - -public partial class BloomContainer : ShaderContainer -{ - protected override string FragmentShader => "Blur"; - public override ShaderType Type => ShaderType.Bloom; - - private Bindable disable; - - public BloomContainer() - { - DrawOriginal = true; - EffectBlending = BlendingParameters.Additive; - EffectPlacement = EffectPlacement.InFront; - } - - [BackgroundDependencyLoader] - private void load(FluXisConfig config) - { - disable = config.GetBindable(FluXisSetting.DisableBloom); - } - - protected override DrawNode CreateShaderDrawNode() => new BloomContainerDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/Bloom/BloomDrawNode.cs b/fluXis/Graphics/Shaders/Bloom/BloomDrawNode.cs deleted file mode 100644 index b3d0667dd..000000000 --- a/fluXis/Graphics/Shaders/Bloom/BloomDrawNode.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osu.Framework.Utils; -using osuTK; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.Bloom; - -public partial class BloomContainer -{ - private class BloomContainerDrawNode : ShaderDrawNode - { - private float strength; - private IUniformBuffer parametersBuffer; - - private int radius; - - public BloomContainerDrawNode(ShaderContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - Source.EffectColour = Color4.White.Opacity(Source.Strength); - strength = 20 * Source.Strength; - radius = Blur.KernelSize(strength); - - base.ApplyState(); - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (strength <= 0 || Source.disable.Value) - return; - - renderer.PushScissorState(false); - - drawFrameBuffer(renderer, radius, strength, 0); - drawFrameBuffer(renderer, radius, strength, 90); - - renderer.PopScissorState(); - } - - private void drawFrameBuffer(IRenderer renderer, int kernelRadius, float sigma, int rotation) - { - parametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - using (BindFrameBuffer(target)) - { - float radians = float.DegreesToRadians(rotation); - - parametersBuffer.Data = parametersBuffer.Data with - { - Radius = kernelRadius, - Sigma = sigma, - TexSize = current.Size, - Direction = new Vector2(MathF.Cos(radians), MathF.Sin(radians)) - }; - - Shader.BindUniformBlock("m_BlurParameters", parametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - parametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct BlurParameters - { - public UniformVector2 TexSize; - public UniformInt Radius; - public UniformFloat Sigma; - public UniformVector2 Direction; - private readonly UniformPadding8 pad1; - } - } -} diff --git a/fluXis/Graphics/Shaders/Bloom/BufferedBloomContainer.cs b/fluXis/Graphics/Shaders/Bloom/BufferedBloomContainer.cs deleted file mode 100644 index 2b5f89e75..000000000 --- a/fluXis/Graphics/Shaders/Bloom/BufferedBloomContainer.cs +++ /dev/null @@ -1,16 +0,0 @@ -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osuTK; - -namespace fluXis.Graphics.Shaders.Bloom; - -public partial class BufferedBloomContainer : BufferedContainer -{ - public BufferedBloomContainer() - { - DrawOriginal = true; - EffectBlending = BlendingParameters.Additive; - EffectPlacement = EffectPlacement.InFront; - BlurSigma = new Vector2(40); - } -} diff --git a/fluXis/Graphics/Shaders/Chromatic/ChromaticContainer.cs b/fluXis/Graphics/Shaders/Chromatic/ChromaticContainer.cs deleted file mode 100644 index 59ac94829..000000000 --- a/fluXis/Graphics/Shaders/Chromatic/ChromaticContainer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Graphics; - -namespace fluXis.Graphics.Shaders.Chromatic; - -public partial class ChromaticContainer : ShaderContainer -{ - protected override string FragmentShader => "ChromaticAberration"; - public override ShaderType Type => ShaderType.Chromatic; - protected override DrawNode CreateShaderDrawNode() => new ChromaticContainerDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/Chromatic/ChromaticDrawNote.cs b/fluXis/Graphics/Shaders/Chromatic/ChromaticDrawNote.cs deleted file mode 100644 index b833729dc..000000000 --- a/fluXis/Graphics/Shaders/Chromatic/ChromaticDrawNote.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Runtime.InteropServices; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.Chromatic; - -public partial class ChromaticContainer -{ - private class ChromaticContainerDrawNode : ShaderDrawNode - { - private float strength; - private IUniformBuffer parametersBuffer; - - public ChromaticContainerDrawNode(ChromaticContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - base.ApplyState(); - - strength = Source.Strength; - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (strength > 0) - drawFrameBuffer(renderer); - } - - private void drawFrameBuffer(IRenderer renderer) - { - parametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - renderer.SetBlend(BlendingParameters.None); - - using (BindFrameBuffer(target)) - { - parametersBuffer.Data = parametersBuffer.Data with - { - TexSize = current.Size, - Radius = strength - }; - - Shader.BindUniformBlock("m_ChromaticParameters", parametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - parametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct ChromaticParameters - { - public UniformVector2 TexSize; - public UniformFloat Radius; - private readonly UniformPadding4 pad1; - } - } -} diff --git a/fluXis/Graphics/Shaders/FishEye/FIshEyeDrawNode.cs b/fluXis/Graphics/Shaders/FishEye/FIshEyeDrawNode.cs deleted file mode 100644 index 624669ae2..000000000 --- a/fluXis/Graphics/Shaders/FishEye/FIshEyeDrawNode.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System.Runtime.InteropServices; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osu.Framework.Utils; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.FishEye; - -public partial class FishEyeContainer -{ - private class FishEyeContainerDrawNode : ShaderDrawNode - { - private float strength; - private IUniformBuffer parametersBuffer; - - public FishEyeContainerDrawNode(FishEyeContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - base.ApplyState(); - - strength = Source.Strength; - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (!Precision.AlmostEquals(strength, 0)) - drawFrameBuffer(renderer); - } - - private void drawFrameBuffer(IRenderer renderer) - { - parametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - renderer.SetBlend(BlendingParameters.None); - - using (BindFrameBuffer(target)) - { - parametersBuffer.Data = parametersBuffer.Data with - { - TexSize = current.Size, - Strength = strength, - }; - - Shader.BindUniformBlock("m_FishEyeParameters", parametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - parametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct FishEyeParameters - { - public UniformVector2 TexSize; - public UniformFloat Strength; - private readonly UniformPadding4 pad1; - } - } -} diff --git a/fluXis/Graphics/Shaders/FishEye/FishEyeContainer.cs b/fluXis/Graphics/Shaders/FishEye/FishEyeContainer.cs deleted file mode 100644 index c024e6e73..000000000 --- a/fluXis/Graphics/Shaders/FishEye/FishEyeContainer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Graphics; - -namespace fluXis.Graphics.Shaders.FishEye; - -public partial class FishEyeContainer : ShaderContainer -{ - protected override string FragmentShader => "FishEye"; - public override ShaderType Type => ShaderType.FishEye; - protected override DrawNode CreateShaderDrawNode() => new FishEyeContainerDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/Glitch/GlitchContainer.cs b/fluXis/Graphics/Shaders/Glitch/GlitchContainer.cs deleted file mode 100644 index 6340e98d9..000000000 --- a/fluXis/Graphics/Shaders/Glitch/GlitchContainer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Graphics; - -namespace fluXis.Graphics.Shaders.Glitch; - -public partial class GlitchContainer : ShaderContainer -{ - protected override string FragmentShader => "Glitch"; - public override ShaderType Type => ShaderType.Glitch; - protected override DrawNode CreateShaderDrawNode() => new GlitchContainerDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/Glitch/GlitchDrawNode.cs b/fluXis/Graphics/Shaders/Glitch/GlitchDrawNode.cs deleted file mode 100644 index 389466242..000000000 --- a/fluXis/Graphics/Shaders/Glitch/GlitchDrawNode.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System.Runtime.InteropServices; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.Glitch; - -public partial class GlitchContainer -{ - private class GlitchContainerDrawNode : ShaderDrawNode - { - private float strength; // x strength - private float strength2; // y strength - private float strength3; // glitch block size - private IUniformBuffer parametersBuffer; - - public GlitchContainerDrawNode(GlitchContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - base.ApplyState(); - - strength = Source.Strength / 10f; - strength2 = Source.Strength2 / 10f; - strength3 = Source.Strength3; - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (strength > 0 || strength2 > 0) - drawFrameBuffer(renderer); - } - - private void drawFrameBuffer(IRenderer renderer) - { - parametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - renderer.SetBlend(BlendingParameters.None); - - using (BindFrameBuffer(target)) - { - parametersBuffer.Data = parametersBuffer.Data with - { - TexSize = current.Size, - StrengthX = strength, - StrengthY = strength2, - BlockSize = strength3, - Time = (float)Source.Time.Current % 10000f - }; - - Shader.BindUniformBlock("m_GlitchParameters", parametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - parametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct GlitchParameters - { - public UniformVector2 TexSize; - public UniformFloat StrengthX; - public UniformFloat StrengthY; - public UniformFloat BlockSize; - public UniformFloat Time; - private readonly UniformPadding8 pad1; - } - } -} diff --git a/fluXis/Graphics/Shaders/Greyscale/GreyscaleContainer.cs b/fluXis/Graphics/Shaders/Greyscale/GreyscaleContainer.cs deleted file mode 100644 index aadd9f8dc..000000000 --- a/fluXis/Graphics/Shaders/Greyscale/GreyscaleContainer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Graphics; - -namespace fluXis.Graphics.Shaders.Greyscale; - -public partial class GreyscaleContainer : ShaderContainer -{ - protected override string FragmentShader => "Greyscale"; - public override ShaderType Type => ShaderType.Greyscale; - protected override DrawNode CreateShaderDrawNode() => new GreyscaleDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/Greyscale/GreyscaleDrawNode.cs b/fluXis/Graphics/Shaders/Greyscale/GreyscaleDrawNode.cs deleted file mode 100644 index 779709964..000000000 --- a/fluXis/Graphics/Shaders/Greyscale/GreyscaleDrawNode.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Runtime.InteropServices; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.Greyscale; - -public partial class GreyscaleContainer -{ - private class GreyscaleDrawNode : ShaderDrawNode - { - private float strength; - private IUniformBuffer parametersBuffer; - - public GreyscaleDrawNode(ShaderContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - base.ApplyState(); - - strength = Source.Strength; - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (strength > 0) - drawFrameBuffer(renderer); - } - - private void drawFrameBuffer(IRenderer renderer) - { - parametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - renderer.SetBlend(BlendingParameters.None); - - using (BindFrameBuffer(target)) - { - parametersBuffer.Data = parametersBuffer.Data with - { - TexSize = current.Size, - Strength = Source.Strength - }; - - Shader.BindUniformBlock("m_GreyscaleParameters", parametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - parametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct GreyscaleParameters - { - public UniformVector2 TexSize; - public UniformFloat Strength; - private readonly UniformPadding4 pad1; - } - } -} diff --git a/fluXis/Graphics/Shaders/HueShift/HueShiftContainer.cs b/fluXis/Graphics/Shaders/HueShift/HueShiftContainer.cs deleted file mode 100644 index a341b2ad3..000000000 --- a/fluXis/Graphics/Shaders/HueShift/HueShiftContainer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Graphics; - -namespace fluXis.Graphics.Shaders.HueShift; - -public partial class HueShiftContainer : ShaderContainer -{ - protected override string FragmentShader => "HueShift"; - public override ShaderType Type => ShaderType.HueShift; - protected override DrawNode CreateShaderDrawNode() => new HueShiftContainerDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/HueShift/HueShiftDrawNode.cs b/fluXis/Graphics/Shaders/HueShift/HueShiftDrawNode.cs deleted file mode 100644 index e06ef3fc2..000000000 --- a/fluXis/Graphics/Shaders/HueShift/HueShiftDrawNode.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Runtime.InteropServices; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.HueShift; - -public partial class HueShiftContainer -{ - private class HueShiftContainerDrawNode : ShaderDrawNode - { - private float strength; - private IUniformBuffer parametersBuffer; - - public HueShiftContainerDrawNode(HueShiftContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - base.ApplyState(); - - strength = Source.Strength; - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (strength > 0) - drawFrameBuffer(renderer); - } - - private void drawFrameBuffer(IRenderer renderer) - { - parametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - renderer.SetBlend(BlendingParameters.None); - - using (BindFrameBuffer(target)) - { - parametersBuffer.Data = parametersBuffer.Data with - { - TexSize = current.Size, - Strength = strength - }; - - Shader.BindUniformBlock("m_HueShiftParameters", parametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - parametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct HueShiftParameters - { - public UniformVector2 TexSize; - public UniformFloat Strength; - private readonly UniformPadding4 pad1; - } - } -} diff --git a/fluXis/Graphics/Shaders/Invert/InvertContainer.cs b/fluXis/Graphics/Shaders/Invert/InvertContainer.cs deleted file mode 100644 index f41631641..000000000 --- a/fluXis/Graphics/Shaders/Invert/InvertContainer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Graphics; - -namespace fluXis.Graphics.Shaders.Invert; - -public partial class InvertContainer : ShaderContainer -{ - protected override string FragmentShader => "Invert"; - public override ShaderType Type => ShaderType.Invert; - protected override DrawNode CreateShaderDrawNode() => new InvertContainerDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/Invert/InvertDrawNode.cs b/fluXis/Graphics/Shaders/Invert/InvertDrawNode.cs deleted file mode 100644 index 6b84a08fd..000000000 --- a/fluXis/Graphics/Shaders/Invert/InvertDrawNode.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Runtime.InteropServices; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.Invert; - -public partial class InvertContainer -{ - private class InvertContainerDrawNode : ShaderDrawNode - { - private float strength; - private IUniformBuffer invertParametersBuffer; - - public InvertContainerDrawNode(InvertContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - base.ApplyState(); - - strength = Source.Strength; - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (strength > 0) - drawFrameBuffer(renderer); - } - - private void drawFrameBuffer(IRenderer renderer) - { - invertParametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - renderer.SetBlend(BlendingParameters.None); - - using (BindFrameBuffer(target)) - { - invertParametersBuffer.Data = invertParametersBuffer.Data with - { - TexSize = current.Size, - Strength = strength - }; - - Shader.BindUniformBlock("m_InvertParameters", invertParametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - invertParametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct InvertParameters - { - public UniformVector2 TexSize; - public UniformFloat Strength; - private readonly UniformPadding4 pad1; - } - } -} diff --git a/fluXis/Graphics/Shaders/Mosaic/MosaicContainer.cs b/fluXis/Graphics/Shaders/Mosaic/MosaicContainer.cs deleted file mode 100644 index bed997c47..000000000 --- a/fluXis/Graphics/Shaders/Mosaic/MosaicContainer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Graphics; - -namespace fluXis.Graphics.Shaders.Mosaic; - -public partial class MosaicContainer : ShaderContainer -{ - protected override string FragmentShader => "Mosaic"; - public override ShaderType Type => ShaderType.Mosaic; - protected override DrawNode CreateShaderDrawNode() => new MosaicDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/Mosaic/MosaicDrawNode.cs b/fluXis/Graphics/Shaders/Mosaic/MosaicDrawNode.cs deleted file mode 100644 index 2b59a4385..000000000 --- a/fluXis/Graphics/Shaders/Mosaic/MosaicDrawNode.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Runtime.InteropServices; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.Mosaic; - -public partial class MosaicContainer -{ - private class MosaicDrawNode : ShaderDrawNode - { - private float strength; - private IUniformBuffer parametersBuffer; - - public MosaicDrawNode(MosaicContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - base.ApplyState(); - - strength = Source.Strength; - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (strength > 0) - drawFrameBuffer(renderer); - } - - private void drawFrameBuffer(IRenderer renderer) - { - parametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - renderer.SetBlend(BlendingParameters.None); - - using (BindFrameBuffer(target)) - { - parametersBuffer.Data = parametersBuffer.Data with - { - TexSize = current.Size, - Strength = strength - }; - - Shader.BindUniformBlock("m_MosaicParameters", parametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - parametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct MosaicParameters - { - public UniformVector2 TexSize; - public UniformFloat Strength; - private readonly UniformPadding4 pad1; - } - } -} diff --git a/fluXis/Graphics/Shaders/Noise/NoiseContainer.cs b/fluXis/Graphics/Shaders/Noise/NoiseContainer.cs deleted file mode 100644 index 1a01d828e..000000000 --- a/fluXis/Graphics/Shaders/Noise/NoiseContainer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Graphics; - -namespace fluXis.Graphics.Shaders.Noise; - -public partial class NoiseContainer : ShaderContainer -{ - protected override string FragmentShader => "Noise"; - public override ShaderType Type => ShaderType.Noise; - protected override DrawNode CreateShaderDrawNode() => new NoiseContainerDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/Noise/NoiseDrawNode.cs b/fluXis/Graphics/Shaders/Noise/NoiseDrawNode.cs deleted file mode 100644 index 306520cef..000000000 --- a/fluXis/Graphics/Shaders/Noise/NoiseDrawNode.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System.Runtime.InteropServices; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.Noise; - -public partial class NoiseContainer -{ - private class NoiseContainerDrawNode : ShaderDrawNode - { - private float strength; - private IUniformBuffer parametersBuffer; - - public NoiseContainerDrawNode(NoiseContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - base.ApplyState(); - - strength = Source.Strength; - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (strength > 0) - drawFrameBuffer(renderer); - } - - private void drawFrameBuffer(IRenderer renderer) - { - parametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - renderer.SetBlend(BlendingParameters.None); - - using (BindFrameBuffer(target)) - { - parametersBuffer.Data = new NoiseParameters - { - TexSize = current.Size, - Strength = strength, - Time = (float)Source.Time.Current / 1000f - }; - - Shader.BindUniformBlock("m_NoiseParameters", parametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - parametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct NoiseParameters - { - public UniformVector2 TexSize; - public UniformFloat Strength; - public UniformFloat Time; - } - } -} diff --git a/fluXis/Graphics/Shaders/Reflections/ReflectionsContainer.cs b/fluXis/Graphics/Shaders/Reflections/ReflectionsContainer.cs deleted file mode 100644 index 7aead4af2..000000000 --- a/fluXis/Graphics/Shaders/Reflections/ReflectionsContainer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Graphics; - -namespace fluXis.Graphics.Shaders.Reflections; - -public partial class ReflectionsContainer : ShaderContainer -{ - protected override string FragmentShader => "Reflections"; - public override ShaderType Type => ShaderType.Reflections; - protected override DrawNode CreateShaderDrawNode() => new ReflectionsContainerDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/Reflections/ReflectionsDrawNode.cs b/fluXis/Graphics/Shaders/Reflections/ReflectionsDrawNode.cs deleted file mode 100644 index ec69eefbf..000000000 --- a/fluXis/Graphics/Shaders/Reflections/ReflectionsDrawNode.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Runtime.InteropServices; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.Reflections; - -public partial class ReflectionsContainer -{ - private class ReflectionsContainerDrawNode : ShaderDrawNode - { - private float strength; - private IUniformBuffer parametersBuffer; - - private float scale; - - public ReflectionsContainerDrawNode(ReflectionsContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - base.ApplyState(); - - strength = Source.Strength; - scale = Source.Strength2; - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (strength != 0) - drawFrameBuffer(renderer); - } - - private void drawFrameBuffer(IRenderer renderer) - { - parametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - renderer.SetBlend(BlendingParameters.None); - - using (BindFrameBuffer(target)) - { - parametersBuffer.Data = parametersBuffer.Data with - { - TexSize = current.Size, - Strength = strength, - Scale = scale, - }; - - Shader.BindUniformBlock("m_ReflectionsParameters", parametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - parametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct ReflectionsParameters - { - public UniformVector2 TexSize; - public UniformFloat Strength; - public UniformFloat Scale; - } - } -} diff --git a/fluXis/Graphics/Shaders/Retro/RetroContainer.cs b/fluXis/Graphics/Shaders/Retro/RetroContainer.cs deleted file mode 100644 index 8975f571f..000000000 --- a/fluXis/Graphics/Shaders/Retro/RetroContainer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Graphics; - -namespace fluXis.Graphics.Shaders.Retro; - -public partial class RetroContainer : ShaderContainer -{ - protected override string FragmentShader => "Retro"; - public override ShaderType Type => ShaderType.Retro; - protected override DrawNode CreateShaderDrawNode() => new RetroContainerDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/Retro/RetroDrawNode.cs b/fluXis/Graphics/Shaders/Retro/RetroDrawNode.cs deleted file mode 100644 index 9f12f2d21..000000000 --- a/fluXis/Graphics/Shaders/Retro/RetroDrawNode.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Runtime.InteropServices; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.Retro; - -public partial class RetroContainer -{ - private class RetroContainerDrawNode : ShaderDrawNode - { - private float strength; - private IUniformBuffer parametersBuffer; - - public RetroContainerDrawNode(RetroContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - base.ApplyState(); - - strength = Source.Strength; - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (strength > 0) - drawFrameBuffer(renderer); - } - - private void drawFrameBuffer(IRenderer renderer) - { - parametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - renderer.SetBlend(BlendingParameters.None); - - using (BindFrameBuffer(target)) - { - parametersBuffer.Data = parametersBuffer.Data with - { - TexSize = current.Size, - Strength = strength - }; - - Shader.BindUniformBlock("m_RetroParameters", parametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - parametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct RetroParameters - { - public UniformVector2 TexSize; - public UniformFloat Strength; - public readonly UniformPadding4 pad1; - } - } -} diff --git a/fluXis/Graphics/Shaders/ShaderStackContainer.cs b/fluXis/Graphics/Shaders/ShaderStackContainer.cs index 19aa9a259..6eb1e7298 100644 --- a/fluXis/Graphics/Shaders/ShaderStackContainer.cs +++ b/fluXis/Graphics/Shaders/ShaderStackContainer.cs @@ -1,33 +1,94 @@ using System.Collections.Generic; using System.Linq; +using fluXis.Graphics.Shaders.Steps; using fluXis.Map.Structures.Events; +using JetBrains.Annotations; +using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders; +using osu.Framework.Layout; +using osuTK; +using osuTK.Graphics; namespace fluXis.Graphics.Shaders; -public partial class ShaderStackContainer : CompositeDrawable +public partial class ShaderStackContainer : CompositeDrawable, IBufferedDrawable { - private readonly List shaders = new(); + [Resolved] + private ShaderManager manager { get; set; } - public IEnumerable TransformHandlers => shaders.Select(x => x.TransformHandler); + private readonly List shaders = new(); + public IEnumerable TransformHandlers => shaders.Select(x => x.TransformHandler); public IReadOnlyList ShaderTypes => shaders.DistinctBy(x => x.Type).Select(x => x.Type).ToList(); + public IShader TextureShader { get; private set; } + public BufferedDrawNodeSharedData SharedData { get; } = new(3, null, false, true); + + public Color4 BackgroundColour => new(0, 0, 0, 0); + public DrawColourInfo? FrameBufferDrawColour => base.DrawColourInfo; + public Vector2 FrameBufferScale => Vector2.One; + + private long updateVersion; + private long childrenUpdateVersion = -1; + + protected override bool RequiresChildrenUpdate => base.RequiresChildrenUpdate && childrenUpdateVersion != updateVersion; + public ShaderStackContainer() { RelativeSizeAxes = Axes.Both; } - public ShaderTransformHandler AddShader(ShaderContainer shader) + [BackgroundDependencyLoader] + private void load() + { + TextureShader = manager.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE); + shaders.ForEach(x => x.LoadShader(manager)); + } + + protected override DrawNode CreateDrawNode() + => new ShaderStackDrawNode(this, new CompositeDrawableDrawNode(this), SharedData); + + public override bool UpdateSubTreeMasking() + { + bool result = base.UpdateSubTreeMasking(); + + childrenUpdateVersion = updateVersion; + return result; + } + + protected override RectangleF ComputeChildMaskingBounds() => ScreenSpaceDrawQuad.AABBFloat; + + protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) + { + bool result = base.OnInvalidate(invalidation, source); + + if ((invalidation & Invalidation.DrawNode) <= 0) return result; + + updateVersion++; + return true; + } + + protected override void Update() { - if (shaders.Count == 0) - InternalChild = shader; - else - shaders.Last().Add(shader); + Invalidate(Invalidation.DrawNode); + base.Update(); + } - if (IsLoaded) - LoadComponent(shader); + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + SharedData.Dispose(); + } + + public ShaderTransformHandler AddShader(ShaderStep shader) + { + if (manager != null) + shader.LoadShader(manager); shaders.Add(shader); return shader.TransformHandler; @@ -35,36 +96,111 @@ public ShaderTransformHandler AddShader(ShaderContainer shader) public ShaderStackContainer AddContent(Drawable[] content) { - if (shaders.Count == 0) - InternalChildren = content; - else - shaders.Last().AddRange(content); - + InternalChildren = content; return this; } public IEnumerable RemoveContent() { - IEnumerable children; + IEnumerable children = InternalChildren.ToArray(); + ClearInternal(false); + return children; + } + + public T GetShader() where T : ShaderContainer + => shaders.FirstOrDefault(s => s.GetType() == typeof(T)) as T; + + public ShaderStep GetShader(ShaderType type) + => shaders.FirstOrDefault(s => s.Type == type); + + [CanBeNull] + public static ShaderStep CreateForType(ShaderType type) => type switch + { + ShaderType.Bloom => new BloomShaderStep(), + ShaderType.Greyscale => new GreyscaleShaderStep(), + ShaderType.Invert => new InvertShaderStep(), + ShaderType.Chromatic => new ChromaticShaderStep(), + ShaderType.Mosaic => new MosaicShaderStep(), + ShaderType.Noise => new NoiseShaderStep(), + ShaderType.Vignette => new VignetteShaderStep(), + ShaderType.Retro => new RetroShaderStep(), + ShaderType.HueShift => new HueShiftShaderStep(), + ShaderType.Glitch => new GlitchShaderStep(), + ShaderType.SplitScreen => new SplitScreenShaderStep(), + ShaderType.FishEye => new FishEyeShaderStep(), + ShaderType.Reflections => new ReflectionsShaderStep(), + _ => null + }; + + private class ShaderStackDrawNode : BufferedDrawNode, ICompositeDrawNode + { + protected new ShaderStackContainer Source => (ShaderStackContainer)base.Source; + protected new CompositeDrawableDrawNode Child => (CompositeDrawableDrawNode)base.Child; - if (shaders.Count == 0) + public List Children { - children = InternalChildren.ToArray(); - ClearInternal(false); + get => Child.Children; + set => Child.Children = value; } - else + + public bool AddChildDrawNodes => RequiresRedraw; + + private long updateVersion; + + public ShaderStackDrawNode(IBufferedDrawable source, DrawNode child, BufferedDrawNodeSharedData sharedData) + : base(source, child, sharedData) { - var last = shaders.Last(); - children = last.Children.ToArray(); - last.Clear(false); } - return children; - } + public override void ApplyState() + { + base.ApplyState(); + updateVersion = Source.updateVersion; + } - public T GetShader() where T : ShaderContainer - => shaders.FirstOrDefault(s => s.GetType() == typeof(T)) as T; + protected override long GetDrawVersion() => updateVersion; - public ShaderContainer GetShader(ShaderType type) - => shaders.FirstOrDefault(s => s.Type == type); + protected override void PopulateContents(IRenderer renderer) + { + base.PopulateContents(renderer); + + foreach (var shader in Source.shaders) + { + shader.Time = Source.Time; + shader.EnsureParameters(renderer); + + if (!shader.ShouldRender) + continue; + + for (int i = 0; i < shader.Passes; i++) + { + IFrameBuffer current = SharedData.CurrentEffectBuffer; + IFrameBuffer target = SharedData.GetNextEffectBuffer(); + shader.TargetBuffer = target; + shader.CurrentPass = i + 1; + + shader.UpdateParameters(current); + renderer.SetBlend(BlendingParameters.None); + + using (BindFrameBuffer(target)) + { + shader.DrawBuffer(renderer, current, target); + } + } + } + } + + protected override void DrawContents(IRenderer renderer) + { + var blend = BlendingParameters.Inherit; + blend.CopyFromParent(Source.Blending); + blend.ApplyDefaultToInherited(); + renderer.SetBlend(blend); + + ColourInfo finalEffectColour = DrawColourInfo.Colour; + finalEffectColour.ApplyChild(Color4.White); + + renderer.DrawFrameBuffer(SharedData.CurrentEffectBuffer, DrawRectangle, finalEffectColour); + } + } } diff --git a/fluXis/Graphics/Shaders/ShaderStep.cs b/fluXis/Graphics/Shaders/ShaderStep.cs new file mode 100644 index 000000000..df02a5991 --- /dev/null +++ b/fluXis/Graphics/Shaders/ShaderStep.cs @@ -0,0 +1,71 @@ +using System; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders; +using osu.Framework.Timing; + +namespace fluXis.Graphics.Shaders; + +public abstract class ShaderStep : IHasStrength +{ + protected virtual string VertexShader => VertexShaderDescriptor.TEXTURE_2; + protected abstract string FragmentShader { get; } + + protected IShader Shader { get; private set; } + + public abstract ShaderType Type { get; } + public ShaderTransformHandler TransformHandler { get; } + + public float Strength { get; set; } + public float Strength2 { get; set; } + public float Strength3 { get; set; } + + public virtual bool ShouldRender => Strength > 0 || Strength2 > 0 || Strength3 > 0; + public virtual int Passes => 1; + + protected SRGBColour DrawColor { get; set; } = Colour4.White; + + public FrameTimeInfo Time { get; set; } + public IFrameBuffer TargetBuffer { get; set; } + public int CurrentPass { get; set; } + + protected ShaderStep() + { + TransformHandler = new ShaderTransformHandler(this); + } + + public virtual void LoadShader(ShaderManager shaders) + { + Shader = shaders.Load(VertexShader, FragmentShader); + } + + public virtual void EnsureParameters(IRenderer renderer) { } + public abstract void UpdateParameters(IFrameBuffer current); + + public virtual void DrawBuffer(IRenderer renderer, IFrameBuffer current, IFrameBuffer target) + { + } +} + +public abstract class ShaderStep : ShaderStep + where T : unmanaged, IEquatable +{ + protected IUniformBuffer ParameterBuffer { get; set; } + + public override void EnsureParameters(IRenderer renderer) => ParameterBuffer ??= renderer.CreateUniformBuffer(); + + public override void DrawBuffer(IRenderer renderer, IFrameBuffer current, IFrameBuffer target) + { + var name = typeof(T).Name; + Shader.BindUniformBlock($"m_{name}", ParameterBuffer); + Shader.Bind(); + DrawFrameBuffer(renderer, current); + Shader.Unbind(); + } + + protected void DrawFrameBuffer(IRenderer renderer, IFrameBuffer buffer) + => renderer.DrawFrameBuffer(buffer, new RectangleF(0, 0, buffer.Texture.Width, buffer.Texture.Height), ColourInfo.SingleColour(DrawColor)); +} diff --git a/fluXis/Graphics/Shaders/ShaderTransformHandler.cs b/fluXis/Graphics/Shaders/ShaderTransformHandler.cs index 0c3d1adce..0394fcd09 100644 --- a/fluXis/Graphics/Shaders/ShaderTransformHandler.cs +++ b/fluXis/Graphics/Shaders/ShaderTransformHandler.cs @@ -1,5 +1,4 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Allocation; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -9,9 +8,7 @@ public partial class ShaderTransformHandler : CompositeComponent, IHasStrength { public override bool RemoveCompletedTransforms => false; - public ShaderType Type => shader.Type; - - private ShaderContainer shader { get; } + private IHasStrength shader { get; } public float Strength { @@ -31,7 +28,7 @@ public float Strength3 set => shader.Strength3 = value; } - public ShaderTransformHandler(ShaderContainer shader) + public ShaderTransformHandler(IHasStrength shader) { this.shader = shader; } diff --git a/fluXis/Graphics/Shaders/SplitScreen/SplitScreenContainer.cs b/fluXis/Graphics/Shaders/SplitScreen/SplitScreenContainer.cs deleted file mode 100644 index 96c4e831a..000000000 --- a/fluXis/Graphics/Shaders/SplitScreen/SplitScreenContainer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Graphics; - -namespace fluXis.Graphics.Shaders.SplitScreen; - -public partial class SplitScreenContainer : ShaderContainer -{ - protected override string FragmentShader => "SplitScreen"; - public override ShaderType Type => ShaderType.SplitScreen; - protected override DrawNode CreateShaderDrawNode() => new SplitScreenContainerDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/SplitScreen/SplitScreenDrawNode.cs b/fluXis/Graphics/Shaders/SplitScreen/SplitScreenDrawNode.cs deleted file mode 100644 index a04c2993d..000000000 --- a/fluXis/Graphics/Shaders/SplitScreen/SplitScreenDrawNode.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System.Runtime.InteropServices; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osuTK; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.SplitScreen; - -public partial class SplitScreenContainer -{ - private class SplitScreenContainerDrawNode : ShaderDrawNode - { - private float strength; - private IUniformBuffer parametersBuffer; - - private int splitsX = 2; - private int splitsY = 2; - - public SplitScreenContainerDrawNode(ShaderContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - base.ApplyState(); - - strength = Source.Strength; - splitsX = (int)Source.Strength2; - splitsY = (int)Source.Strength3; - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (strength > 0) - drawFrameBuffer(renderer); - } - - private void drawFrameBuffer(IRenderer renderer) - { - parametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - renderer.SetBlend(BlendingParameters.None); - - using (BindFrameBuffer(target)) - { - parametersBuffer.Data = parametersBuffer.Data with - { - TexSize = current.Size, - SplitsInv = new Vector2(1.0f / splitsX, 1.0f / splitsY), - Strength = strength, - SplitsX = splitsX, - SplitsY = splitsY, - }; - - Shader.BindUniformBlock("m_SplitScreenParameters", parametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - parametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct SplitScreenParameters - { - public UniformVector2 TexSize; - public UniformVector2 SplitsInv; - public UniformFloat Strength; - public UniformInt SplitsX; - public UniformInt SplitsY; - private readonly UniformPadding4 pad1; - } - } -} diff --git a/fluXis/Graphics/Shaders/Steps/BloomShaderStep.cs b/fluXis/Graphics/Shaders/Steps/BloomShaderStep.cs new file mode 100644 index 000000000..f1efeaf57 --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/BloomShaderStep.cs @@ -0,0 +1,111 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders; +using osu.Framework.Graphics.Shaders.Types; +using osu.Framework.Utils; +using osuTK; + +namespace fluXis.Graphics.Shaders.Steps; + +public class BloomShaderStep : ShaderStep +{ + protected override string FragmentShader => "Blur"; + protected string ComposeFragmentShader => "BlurCompose"; + private IShader blurComposeShader; + private IUniformBuffer composeParameterBuffer; + public override ShaderType Type => ShaderType.Bloom; + + public override int Passes => 1; + + private int kernelRadius; + private float sigma; + private Vector2 direction; + + public override void EnsureParameters(IRenderer renderer) + { + ParameterBuffer ??= renderer.CreateUniformBuffer(); + composeParameterBuffer ??= renderer.CreateUniformBuffer(); + } + + public override void UpdateParameters(IFrameBuffer current) + { + ParameterBuffer.Data = ParameterBuffer.Data with + { + Radius = kernelRadius, + Sigma = sigma, + TexSize = current.Size, + Direction = direction + }; + composeParameterBuffer.Data = composeParameterBuffer.Data with + { + Strength = Strength + }; + } + + public override void LoadShader(ShaderManager shaders) + { + base.LoadShader(shaders); + blurComposeShader = shaders.Load(VertexShader, ComposeFragmentShader); + } + + private IFrameBuffer buffer; + private IFrameBuffer buffer2; + + private void drawBlurPass(IRenderer renderer, IFrameBuffer src, IFrameBuffer dst, Vector2 blurDirection) + { + direction = blurDirection; + UpdateParameters(src); + Shader.BindUniformBlock($"m_{nameof(BlurParameters)}", ParameterBuffer); + dst.Bind(); + Shader.Bind(); + + DrawFrameBuffer(renderer, src); + + Shader.Unbind(); + dst.Unbind(); + } + + public override void DrawBuffer(IRenderer renderer, IFrameBuffer current, IFrameBuffer target) + { + sigma = 20 * Strength; + kernelRadius = Blur.KernelSize(sigma); + DrawColor = Colour4.White; + + buffer ??= renderer.CreateFrameBuffer(); + buffer.Size = current.Size; + buffer2 ??= renderer.CreateFrameBuffer(); + buffer2.Size = current.Size; + + target.Unbind(); + + drawBlurPass(renderer, current, buffer, Vector2.UnitX); + drawBlurPass(renderer, buffer, buffer2, Vector2.UnitY); + + blurComposeShader.BindUniformBlock($"m_{nameof(BlurComposeParameters)}", composeParameterBuffer); + target.Bind(); + + blurComposeShader.Bind(); + renderer.BindTexture(buffer2.Texture, 1); + DrawFrameBuffer(renderer, current); + blurComposeShader.Unbind(); + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct BlurParameters + { + public UniformVector2 TexSize; + public UniformInt Radius; + public UniformFloat Sigma; + public UniformVector2 Direction; + private readonly UniformPadding8 pad1; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct BlurComposeParameters + { + public UniformFloat Strength; + private readonly UniformPadding12 pad1; + } +} diff --git a/fluXis/Graphics/Shaders/Steps/ChromaticShaderStep.cs b/fluXis/Graphics/Shaders/Steps/ChromaticShaderStep.cs new file mode 100644 index 000000000..5989dabe6 --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/ChromaticShaderStep.cs @@ -0,0 +1,26 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders.Types; + +namespace fluXis.Graphics.Shaders.Steps; + +public class ChromaticShaderStep : ShaderStep +{ + protected override string FragmentShader => "ChromaticAberration"; + public override ShaderType Type => ShaderType.Chromatic; + + public override void UpdateParameters(IFrameBuffer current) => ParameterBuffer.Data = ParameterBuffer.Data with + { + TexSize = current.Size, + Radius = Strength + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct ChromaticParameters + { + public UniformVector2 TexSize; + public UniformFloat Radius; + private readonly UniformPadding4 pad1; + } +} diff --git a/fluXis/Graphics/Shaders/Steps/FishEyeShaderStep.cs b/fluXis/Graphics/Shaders/Steps/FishEyeShaderStep.cs new file mode 100644 index 000000000..3aabbb736 --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/FishEyeShaderStep.cs @@ -0,0 +1,28 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders.Types; + +namespace fluXis.Graphics.Shaders.Steps; + +public class FishEyeShaderStep : ShaderStep +{ + protected override string FragmentShader => "FishEye"; + public override ShaderType Type => ShaderType.FishEye; + + public override bool ShouldRender => Strength != 0; + + public override void UpdateParameters(IFrameBuffer current) => ParameterBuffer.Data = ParameterBuffer.Data with + { + TexSize = current.Size, + Strength = Strength, + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct FishEyeParameters + { + public UniformVector2 TexSize; + public UniformFloat Strength; + private readonly UniformPadding4 pad1; + } +} diff --git a/fluXis/Graphics/Shaders/Steps/GlitchShaderStep.cs b/fluXis/Graphics/Shaders/Steps/GlitchShaderStep.cs new file mode 100644 index 000000000..820a21bb8 --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/GlitchShaderStep.cs @@ -0,0 +1,32 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders.Types; + +namespace fluXis.Graphics.Shaders.Steps; + +public class GlitchShaderStep : ShaderStep +{ + protected override string FragmentShader => "Glitch"; + public override ShaderType Type => ShaderType.Glitch; + + public override void UpdateParameters(IFrameBuffer current) => ParameterBuffer.Data = ParameterBuffer.Data with + { + TexSize = current.Size, + StrengthX = Strength / 10f, + StrengthY = Strength2 / 10f, + BlockSize = Strength3, + Time = (float)Time.Current % 10000f + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct GlitchParameters + { + public UniformVector2 TexSize; + public UniformFloat StrengthX; + public UniformFloat StrengthY; + public UniformFloat BlockSize; + public UniformFloat Time; + private readonly UniformPadding8 pad1; + } +} diff --git a/fluXis/Graphics/Shaders/Steps/GreyscaleShaderStep.cs b/fluXis/Graphics/Shaders/Steps/GreyscaleShaderStep.cs new file mode 100644 index 000000000..451fe30bd --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/GreyscaleShaderStep.cs @@ -0,0 +1,26 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders.Types; + +namespace fluXis.Graphics.Shaders.Steps; + +public class GreyscaleShaderStep : ShaderStep +{ + protected override string FragmentShader => "Greyscale"; + public override ShaderType Type => ShaderType.Greyscale; + + public override void UpdateParameters(IFrameBuffer current) => ParameterBuffer.Data = ParameterBuffer.Data with + { + TexSize = current.Size, + Strength = Strength + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct GreyscaleParameters + { + public UniformVector2 TexSize; + public UniformFloat Strength; + private readonly UniformPadding4 pad1; + } +} diff --git a/fluXis/Graphics/Shaders/Steps/HueShiftShaderStep.cs b/fluXis/Graphics/Shaders/Steps/HueShiftShaderStep.cs new file mode 100644 index 000000000..fbb102f28 --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/HueShiftShaderStep.cs @@ -0,0 +1,26 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders.Types; + +namespace fluXis.Graphics.Shaders.Steps; + +public class HueShiftShaderStep : ShaderStep +{ + protected override string FragmentShader => "HueShift"; + public override ShaderType Type => ShaderType.HueShift; + + public override void UpdateParameters(IFrameBuffer current) => ParameterBuffer.Data = ParameterBuffer.Data with + { + TexSize = current.Size, + Strength = Strength + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct HueShiftParameters + { + public UniformVector2 TexSize; + public UniformFloat Strength; + private readonly UniformPadding4 pad1; + } +} diff --git a/fluXis/Graphics/Shaders/Steps/InvertShaderStep.cs b/fluXis/Graphics/Shaders/Steps/InvertShaderStep.cs new file mode 100644 index 000000000..169b9a9e3 --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/InvertShaderStep.cs @@ -0,0 +1,26 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders.Types; + +namespace fluXis.Graphics.Shaders.Steps; + +public class InvertShaderStep : ShaderStep +{ + protected override string FragmentShader => "Invert"; + public override ShaderType Type => ShaderType.Invert; + + public override void UpdateParameters(IFrameBuffer current) => ParameterBuffer.Data = ParameterBuffer.Data with + { + TexSize = current.Size, + Strength = Strength, + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct InvertParameters + { + public UniformVector2 TexSize; + public UniformFloat Strength; + private readonly UniformPadding4 pad1; + } +} diff --git a/fluXis/Graphics/Shaders/Steps/MosaicShaderStep.cs b/fluXis/Graphics/Shaders/Steps/MosaicShaderStep.cs new file mode 100644 index 000000000..ff7fd8719 --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/MosaicShaderStep.cs @@ -0,0 +1,26 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders.Types; + +namespace fluXis.Graphics.Shaders.Steps; + +public class MosaicShaderStep : ShaderStep +{ + protected override string FragmentShader => "Mosaic"; + public override ShaderType Type => ShaderType.Mosaic; + + public override void UpdateParameters(IFrameBuffer current) => ParameterBuffer.Data = ParameterBuffer.Data with + { + TexSize = current.Size, + Strength = Strength + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct MosaicParameters + { + public UniformVector2 TexSize; + public UniformFloat Strength; + private readonly UniformPadding4 pad1; + } +} diff --git a/fluXis/Graphics/Shaders/Steps/NoiseShaderStep.cs b/fluXis/Graphics/Shaders/Steps/NoiseShaderStep.cs new file mode 100644 index 000000000..e955f9326 --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/NoiseShaderStep.cs @@ -0,0 +1,27 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders.Types; + +namespace fluXis.Graphics.Shaders.Steps; + +public class NoiseShaderStep : ShaderStep +{ + protected override string FragmentShader => "Noise"; + public override ShaderType Type => ShaderType.Noise; + + public override void UpdateParameters(IFrameBuffer current) => ParameterBuffer.Data = new NoiseParameters + { + TexSize = current.Size, + Strength = Strength, + Time = (float)(Time.Current / 1000f) + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct NoiseParameters + { + public UniformVector2 TexSize; + public UniformFloat Strength; + public UniformFloat Time; + } +} diff --git a/fluXis/Graphics/Shaders/Steps/ReflectionsShaderStep.cs b/fluXis/Graphics/Shaders/Steps/ReflectionsShaderStep.cs new file mode 100644 index 000000000..a03d5c116 --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/ReflectionsShaderStep.cs @@ -0,0 +1,29 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders.Types; + +namespace fluXis.Graphics.Shaders.Steps; + +public class ReflectionsShaderStep : ShaderStep +{ + protected override string FragmentShader => "Reflections"; + public override ShaderType Type => ShaderType.Reflections; + + public override bool ShouldRender => Strength > 0; + + public override void UpdateParameters(IFrameBuffer current) => ParameterBuffer.Data = new ReflectionsParameters + { + TexSize = current.Size, + Strength = Strength, + Scale = Strength2 + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct ReflectionsParameters + { + public UniformVector2 TexSize; + public UniformFloat Strength; + public UniformFloat Scale; + } +} diff --git a/fluXis/Graphics/Shaders/Steps/RetroShaderStep.cs b/fluXis/Graphics/Shaders/Steps/RetroShaderStep.cs new file mode 100644 index 000000000..923e35839 --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/RetroShaderStep.cs @@ -0,0 +1,26 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders.Types; + +namespace fluXis.Graphics.Shaders.Steps; + +public class RetroShaderStep : ShaderStep +{ + protected override string FragmentShader => "Retro"; + public override ShaderType Type => ShaderType.Retro; + + public override void UpdateParameters(IFrameBuffer current) => ParameterBuffer.Data = ParameterBuffer.Data with + { + TexSize = current.Size, + Strength = Strength + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct RetroParameters + { + public UniformVector2 TexSize; + public UniformFloat Strength; + private readonly UniformPadding4 pad1; + } +} diff --git a/fluXis/Graphics/Shaders/Steps/SplitScreenShaderStep.cs b/fluXis/Graphics/Shaders/Steps/SplitScreenShaderStep.cs new file mode 100644 index 000000000..38c89d3d6 --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/SplitScreenShaderStep.cs @@ -0,0 +1,35 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders.Types; +using osuTK; + +namespace fluXis.Graphics.Shaders.Steps; + +public class SplitScreenShaderStep : ShaderStep +{ + protected override string FragmentShader => "SplitScreen"; + public override ShaderType Type => ShaderType.SplitScreen; + + public override bool ShouldRender => Strength > 0; + + public override void UpdateParameters(IFrameBuffer current) => ParameterBuffer.Data = ParameterBuffer.Data with + { + TexSize = current.Size, + SplitsInv = new Vector2(1.0f / Strength2, 1.0f / Strength3), + Strength = Strength, + SplitsX = (int)Strength2, + SplitsY = (int)Strength3 + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct SplitScreenParameters + { + public UniformVector2 TexSize; + public UniformVector2 SplitsInv; + public UniformFloat Strength; + public UniformInt SplitsX; + public UniformInt SplitsY; + private readonly UniformPadding4 pad1; + } +} diff --git a/fluXis/Graphics/Shaders/Steps/VignetteShaderStep.cs b/fluXis/Graphics/Shaders/Steps/VignetteShaderStep.cs new file mode 100644 index 000000000..cc88f6760 --- /dev/null +++ b/fluXis/Graphics/Shaders/Steps/VignetteShaderStep.cs @@ -0,0 +1,26 @@ +using System.Runtime.InteropServices; +using fluXis.Map.Structures.Events; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders.Types; + +namespace fluXis.Graphics.Shaders.Steps; + +public class VignetteShaderStep : ShaderStep +{ + protected override string FragmentShader => "Vignette"; + public override ShaderType Type => ShaderType.Vignette; + + public override void UpdateParameters(IFrameBuffer current) => ParameterBuffer.Data = ParameterBuffer.Data with + { + TexSize = current.Size, + Strength = Strength + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct VignetteParameters + { + public UniformVector2 TexSize; + public UniformFloat Strength; + private readonly UniformPadding4 pad1; + } +} diff --git a/fluXis/Graphics/Shaders/Vignette/VignetteContainer.cs b/fluXis/Graphics/Shaders/Vignette/VignetteContainer.cs deleted file mode 100644 index b31217ecb..000000000 --- a/fluXis/Graphics/Shaders/Vignette/VignetteContainer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using fluXis.Map.Structures.Events; -using osu.Framework.Graphics; - -namespace fluXis.Graphics.Shaders.Vignette; - -public partial class VignetteContainer : ShaderContainer -{ - protected override string FragmentShader => "Vignette"; - public override ShaderType Type => ShaderType.Vignette; - protected override DrawNode CreateShaderDrawNode() => new VignetteContainerDrawNode(this, SharedData); -} diff --git a/fluXis/Graphics/Shaders/Vignette/VignetteDrawNode.cs b/fluXis/Graphics/Shaders/Vignette/VignetteDrawNode.cs deleted file mode 100644 index 1cc45397d..000000000 --- a/fluXis/Graphics/Shaders/Vignette/VignetteDrawNode.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Runtime.InteropServices; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Rendering; -using osu.Framework.Graphics.Shaders.Types; -using osuTK.Graphics; - -namespace fluXis.Graphics.Shaders.Vignette; - -public partial class VignetteContainer -{ - private class VignetteContainerDrawNode : ShaderDrawNode - { - private float strength; - private IUniformBuffer parametersBuffer; - - public VignetteContainerDrawNode(VignetteContainer source, BufferedDrawNodeSharedData sharedData) - : base(source, sharedData) - { - } - - public override void ApplyState() - { - base.ApplyState(); - - strength = Source.Strength; - } - - protected override void PopulateContents(IRenderer renderer) - { - base.PopulateContents(renderer); - - if (strength > 0) - drawFrameBuffer(renderer); - } - - private void drawFrameBuffer(IRenderer renderer) - { - parametersBuffer ??= renderer.CreateUniformBuffer(); - - IFrameBuffer current = SharedData.CurrentEffectBuffer; - IFrameBuffer target = SharedData.GetNextEffectBuffer(); - - renderer.SetBlend(BlendingParameters.None); - - using (BindFrameBuffer(target)) - { - parametersBuffer.Data = parametersBuffer.Data with - { - TexSize = current.Size, - Strength = strength - }; - - Shader.BindUniformBlock("m_VignetteParameters", parametersBuffer); - Shader.Bind(); - renderer.DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); - Shader.Unbind(); - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - parametersBuffer?.Dispose(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private record struct VignetteParameters - { - public UniformVector2 TexSize; - public UniformFloat Strength; - public readonly UniformPadding4 Pad; - } - } -} diff --git a/fluXis/Overlay/Settings/UI/Keybind/SettingsAbstractKeybind.cs b/fluXis/Overlay/Settings/UI/Keybind/SettingsAbstractKeybind.cs index bf88882c4..2d00be596 100644 --- a/fluXis/Overlay/Settings/UI/Keybind/SettingsAbstractKeybind.cs +++ b/fluXis/Overlay/Settings/UI/Keybind/SettingsAbstractKeybind.cs @@ -23,6 +23,7 @@ public abstract partial class SettingsAbstractKeybind : SettingsItem where T : Enum { public override bool AcceptsFocus => true; + public override bool RequestsFocus => index >= 0; [Resolved] private ReadableKeyCombinationProvider keyCombinationProvider { get; set; } @@ -179,6 +180,15 @@ protected override bool OnMidiDown(MidiDownEvent e) return true; } + protected override bool ActivateFocus() + { + if (!Enabled) + return true; + + TriggerClick(); + return true; + } + private void updateBinding(KeyCombination combination, InputKey key) => updateBinding(new KeyCombination(combination.Keys.Where(KeyCombination.IsModifierKey).Append(key).ToArray())); private void updateBinding(KeyCombination combination) diff --git a/fluXis/Screens/Edit/Tabs/Charting/Playfield/EditorHitObject.cs b/fluXis/Screens/Edit/Tabs/Charting/Playfield/EditorHitObject.cs index 3e6ebede7..4afb2025f 100644 --- a/fluXis/Screens/Edit/Tabs/Charting/Playfield/EditorHitObject.cs +++ b/fluXis/Screens/Edit/Tabs/Charting/Playfield/EditorHitObject.cs @@ -24,7 +24,7 @@ public abstract partial class EditorHitObject : CompositeDrawable public HitObject Data { get; } - public virtual bool Visible => Math.Abs(EditorClock.CurrentTime - Data.Time) <= 2000; + public virtual bool Visible => Math.Abs(EditorClock.CurrentTime - Data.Time) <= 2000 / settings.Zoom; private FluXisSpriteText text { get; set; } diff --git a/fluXis/Screens/Edit/Tabs/Design/DesignContainer.cs b/fluXis/Screens/Edit/Tabs/Design/DesignContainer.cs index 58696c80b..79014092d 100644 --- a/fluXis/Screens/Edit/Tabs/Design/DesignContainer.cs +++ b/fluXis/Screens/Edit/Tabs/Design/DesignContainer.cs @@ -5,19 +5,6 @@ using fluXis.Graphics.Background; using fluXis.Graphics.Containers; using fluXis.Graphics.Shaders; -using fluXis.Graphics.Shaders.Bloom; -using fluXis.Graphics.Shaders.Chromatic; -using fluXis.Graphics.Shaders.Glitch; -using fluXis.Graphics.Shaders.Greyscale; -using fluXis.Graphics.Shaders.HueShift; -using fluXis.Graphics.Shaders.Invert; -using fluXis.Graphics.Shaders.Mosaic; -using fluXis.Graphics.Shaders.Noise; -using fluXis.Graphics.Shaders.Retro; -using fluXis.Graphics.Shaders.Vignette; -using fluXis.Graphics.Shaders.SplitScreen; -using fluXis.Graphics.Shaders.FishEye; -using fluXis.Graphics.Shaders.Reflections; using fluXis.Graphics.Sprites; using fluXis.Map.Structures.Bases; using fluXis.Map.Structures.Events; @@ -210,7 +197,9 @@ private ShaderStackContainer createShaderStack() foreach (var type in shaderTypes) { - ShaderContainer shader = type switch + var shader = ShaderStackContainer.CreateForType(type); + + /*ShaderStep shader = type switch { ShaderType.Chromatic => new ChromaticContainer(), ShaderType.Greyscale => new GreyscaleContainer(), @@ -226,12 +215,11 @@ private ShaderStackContainer createShaderStack() ShaderType.FishEye => new FishEyeContainer(), ShaderType.Reflections => new ReflectionsContainer(), _ => null - }; + };*/ if (shader is null) continue; - shader.RelativeSizeAxes = Axes.Both; shaders.AddShader(shader); } diff --git a/fluXis/Screens/Gameplay/GameplayScreen.cs b/fluXis/Screens/Gameplay/GameplayScreen.cs index 9946e0642..d43d3a84a 100644 --- a/fluXis/Screens/Gameplay/GameplayScreen.cs +++ b/fluXis/Screens/Gameplay/GameplayScreen.cs @@ -13,23 +13,9 @@ using fluXis.Graphics.Background; using fluXis.Graphics.Containers; using fluXis.Graphics.Shaders; -using fluXis.Graphics.Shaders.Bloom; -using fluXis.Graphics.Shaders.Chromatic; -using fluXis.Graphics.Shaders.Glitch; -using fluXis.Graphics.Shaders.Greyscale; -using fluXis.Graphics.Shaders.HueShift; -using fluXis.Graphics.Shaders.Invert; -using fluXis.Graphics.Shaders.Mosaic; -using fluXis.Graphics.Shaders.Noise; -using fluXis.Graphics.Shaders.Retro; -using fluXis.Graphics.Shaders.Vignette; -using fluXis.Graphics.Shaders.SplitScreen; -using fluXis.Graphics.Shaders.FishEye; -using fluXis.Graphics.Shaders.Reflections; using fluXis.Input; using fluXis.Map; using fluXis.Map.Structures.Bases; -using fluXis.Map.Structures.Events; using fluXis.Mods; using fluXis.Online; using fluXis.Online.Activity; @@ -370,27 +356,9 @@ private ShaderStackContainer buildShaders() var shaders = MapEvents.ShaderEvents; var shaderTypes = shaders.Select(e => e.Type).Distinct().ToList(); - LoadComponent(stack); - foreach (var shaderType in shaderTypes) { - ShaderContainer shader = shaderType switch - { - ShaderType.Chromatic => new ChromaticContainer(), - ShaderType.Greyscale => new GreyscaleContainer(), - ShaderType.Invert => new InvertContainer(), - ShaderType.Bloom => new BloomContainer(), - ShaderType.Mosaic => new MosaicContainer(), - ShaderType.Noise => new NoiseContainer(), - ShaderType.Vignette => new VignetteContainer(), - ShaderType.Retro => new RetroContainer(), - ShaderType.HueShift => new HueShiftContainer(), - ShaderType.Glitch => new GlitchContainer(), - ShaderType.SplitScreen => new SplitScreenContainer(), - ShaderType.FishEye => new FishEyeContainer(), - ShaderType.Reflections => new ReflectionsContainer(), - _ => null - }; + var shader = ShaderStackContainer.CreateForType(shaderType); if (shader == null) { @@ -398,7 +366,6 @@ private ShaderStackContainer buildShaders() continue; } - shader.RelativeSizeAxes = Axes.Both; var handler = stack.AddShader(shader); LoadComponent(handler); @@ -406,6 +373,7 @@ private ShaderStackContainer buildShaders() .ForEach(s => s.Apply(handler)); } + LoadComponent(stack); return stack; } diff --git a/fluXis/Screens/Multiplayer/SubScreens/MultiModeSelect.cs b/fluXis/Screens/Multiplayer/SubScreens/MultiModeSelect.cs index ba98bb650..035689b3f 100644 --- a/fluXis/Screens/Multiplayer/SubScreens/MultiModeSelect.cs +++ b/fluXis/Screens/Multiplayer/SubScreens/MultiModeSelect.cs @@ -1,7 +1,6 @@ using fluXis.Graphics; -using fluXis.Graphics.Shaders.Bloom; -using fluXis.Graphics.Shaders.Chromatic; -using fluXis.Graphics.Shaders.Glitch; +using fluXis.Graphics.Shaders; +using fluXis.Graphics.Shaders.Steps; using fluXis.Graphics.Sprites.Icons; using fluXis.Graphics.Sprites.Text; using fluXis.Graphics.UserInterface.Buttons; @@ -41,8 +40,8 @@ public partial class MultiModeSelect : MultiSubScreen private int clickCount; private FluXisTextFlow hiddenText; - private GlitchContainer glitch; - private ChromaticContainer chroma; + private ShaderTransformHandler glitch; + private ShaderTransformHandler chroma; private Box redBox; private Container buttons; @@ -53,99 +52,97 @@ public partial class MultiModeSelect : MultiSubScreen [BackgroundDependencyLoader] private void load() { - InternalChild = glitch = new GlitchContainer + var shaders = new ShaderStackContainer { RelativeSizeAxes = Axes.Both }; + glitch = shaders.AddShader(new GlitchShaderStep()); + chroma = shaders.AddShader(new ChromaticShaderStep()); + + InternalChild = shaders.AddContent(new Drawable[] { - RelativeSizeAxes = Axes.Both, - Child = chroma = new ChromaticContainer + glitch, + chroma, + redBox = new Box + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(2f), + Alpha = 0, + Colour = Theme.Red + }, + buttons = new Container() { RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - redBox = new Box + hiddenText = new FluXisTextFlow { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(2f), - Alpha = 0, - Colour = Theme.Red + AutoSizeAxes = Axes.X, + TextAnchor = Anchor.TopCentre, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + X = 200, + FontSize = 48, + Alpha = 0 }, - buttons = new BloomContainer + rankedButton = new MultiModeButton { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + /*Title = "Ranked", + Description = "Compete with other players in 1v1\nmatches to climb the leaderboard.",*/ + Title = "???", + Description = "???", + Background = "ranked", + RightSide = false, + Locked = true, + // Action = () => this.Push(new MultiRankedMain()), + Action = () => { - hiddenText = new FluXisTextFlow - { - AutoSizeAxes = Axes.X, - TextAnchor = Anchor.TopCentre, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - X = 200, - FontSize = 48, - Alpha = 0 - }, - rankedButton = new MultiModeButton - { - /*Title = "Ranked", - Description = "Compete with other players in 1v1\nmatches to climb the leaderboard.",*/ - Title = "???", - Description = "???", - Background = "ranked", - RightSide = false, - Locked = true, - // Action = () => this.Push(new MultiRankedMain()), - Action = () => - { - this.Shake(200, 15); - redBox.FadeTo(.5f).FadeOut(600); - - chroma.StrengthTo(16).StrengthTo(0, Styling.TRANSITION_MOVE, Easing.OutQuint); - glitch.StrengthTo(1).Strength2To(1).Strength3To(.04f) - .StrengthTo(0, Styling.TRANSITION_MOVE, Easing.OutQuint) - .Strength2To(0, Styling.TRANSITION_MOVE, Easing.OutQuint) - .Strength3To(0, Styling.TRANSITION_MOVE, Easing.OutQuint); - - if (++clickCount < max_clicks) - return; - - rankedButton.FadeOut(); - hiddenText.FadeIn(); - }, - HoverAction = () => mode.Value = Mode.Ranked, - HoverLostAction = () => mode.Value = Mode.None - }, - openLobbyButton = new MultiModeButton - { - Title = "Open Lobby", - Description = "Play freely against your\nfriends with no restrictions.", - Background = "lobby", - RightSide = true, - Action = () => OpenList(), - HoverAction = () => mode.Value = Mode.OpenLobby, - HoverLostAction = () => mode.Value = Mode.None - } - } - }, - backButton = new CornerButton - { - Corner = Corner.BottomLeft, - ButtonText = LocalizationStrings.General.Back, - Icon = FontAwesome6.Solid.AngleLeft, - Action = this.Exit + this.Shake(200, 15); + redBox.FadeTo(.5f).FadeOut(600); + + chroma.StrengthTo(16).StrengthTo(0, Styling.TRANSITION_MOVE, Easing.OutQuint); + glitch.StrengthTo(1).Strength2To(1).Strength3To(.04f) + .StrengthTo(0, Styling.TRANSITION_MOVE, Easing.OutQuint) + .Strength2To(0, Styling.TRANSITION_MOVE, Easing.OutQuint) + .Strength3To(0, Styling.TRANSITION_MOVE, Easing.OutQuint); + + if (++clickCount < max_clicks) + return; + + rankedButton.FadeOut(); + hiddenText.FadeIn(); + }, + HoverAction = () => mode.Value = Mode.Ranked, + HoverLostAction = () => mode.Value = Mode.None }, - new FluXisSpriteText + openLobbyButton = new MultiModeButton { - Text = "Multiplayer is very much a work in progress. Expect issues.", - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Shadow = true, - WebFontSize = 24, - Y = -100 + Title = "Open Lobby", + Description = "Play freely against your\nfriends with no restrictions.", + Background = "lobby", + RightSide = true, + Action = () => OpenList(), + HoverAction = () => mode.Value = Mode.OpenLobby, + HoverLostAction = () => mode.Value = Mode.None } } }, - }; + backButton = new CornerButton + { + Corner = Corner.BottomLeft, + ButtonText = LocalizationStrings.General.Back, + Icon = FontAwesome6.Solid.AngleLeft, + Action = this.Exit + }, + new FluXisSpriteText + { + Text = "Multiplayer is very much a work in progress. Expect issues.", + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Shadow = true, + WebFontSize = 24, + Y = -100 + } + }); } protected override void LoadComplete()