diff --git a/Content.Client/_DV/Options/UI/Tabs/DeltaTab.xaml b/Content.Client/_DV/Options/UI/Tabs/DeltaTab.xaml index c77c45ea7f..87f1230030 100644 --- a/Content.Client/_DV/Options/UI/Tabs/DeltaTab.xaml +++ b/Content.Client/_DV/Options/UI/Tabs/DeltaTab.xaml @@ -14,6 +14,7 @@ FontColorOverride="{xNamespace:Static s:StyleNano.NanoGold}" StyleClasses="LabelKeyText"/> + OverlaySpace.WorldSpace; + private readonly ShaderInstance _glimmerShader; + private readonly ProtoId _shaderProto = "HighGlimmer"; + + private float _visualGlimmerLevel = 0f; + public int ActualGlimmerLevel = 0; + + public GlimmerOverlay() + { + IoCManager.InjectDependencies(this); + _glimmerShader = _prototype.Index(_shaderProto).Instance().Duplicate(); + } + + protected override bool BeforeDraw(in OverlayDrawArgs args) + { + if (_player.LocalEntity == null) + { + return false; + } + + return base.BeforeDraw(in args); + } + + protected override void Draw(in OverlayDrawArgs args) + { + var lastFrameTime = (float) _timing.FrameTime.TotalSeconds; + + // lerp glimmer level to avoid jumps + _visualGlimmerLevel = !MathHelper.CloseTo(_visualGlimmerLevel, ActualGlimmerLevel, 0.001f) + ? float.Lerp(_visualGlimmerLevel, ActualGlimmerLevel, 0.1f * lastFrameTime) + : ActualGlimmerLevel; + + // clamp glimmer to 0-1, map to exponential ease-out + var progress = Math.Clamp((_visualGlimmerLevel - 700f) / 300f,0,1); + var size = 1f - MathF.Pow(2f, -8f * progress); + + _glimmerShader.SetParameter("size",size); + + var worldHandle = args.WorldHandle; + var viewport = args.WorldBounds; + worldHandle.UseShader(_glimmerShader); + worldHandle.DrawRect(viewport, Color.White); + worldHandle.UseShader(null); + } + + // used to avoid lerp jump if overlay was removed weirdly prior + public void Reset() + { + _visualGlimmerLevel = ActualGlimmerLevel; + } + +} diff --git a/Content.Client/_DV/Overlays/GlimmerOverlaySystem.cs b/Content.Client/_DV/Overlays/GlimmerOverlaySystem.cs new file mode 100644 index 0000000000..fd27be58fc --- /dev/null +++ b/Content.Client/_DV/Overlays/GlimmerOverlaySystem.cs @@ -0,0 +1,64 @@ +using Content.Shared._DV.CCVars; +using Content.Shared.Psionics.Glimmer; +using Robust.Client.Graphics; +using Robust.Shared.Configuration; + +namespace Content.Client._DV.Overlays; + +public sealed partial class GlimmerOverlaySystem : EntitySystem +{ + [Dependency] private readonly IOverlayManager _overlayMan = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; + + private GlimmerOverlay _overlay = default!; + + private bool _cvarDisabled; + + public override void Initialize() + { + base.Initialize(); + + _overlay = new GlimmerOverlay(); + SubscribeNetworkEvent(OnGlimmerChanged); + _cfg.OnValueChanged(DCCVars.DisableGlimmerShader, OnDisableGlimmerShaderChanged); + } + + private void OnGlimmerChanged(GlimmerChangedEvent eventArgs) + { + if(_cvarDisabled) + return; + + if(eventArgs.Glimmer > 700) + { + _overlay.ActualGlimmerLevel = eventArgs.Glimmer; + if (!_overlayMan.HasOverlay()) + { + _overlay.Reset(); + _overlayMan.AddOverlay(_overlay); + } + } + else + { + if (_overlayMan.HasOverlay()) + { + _overlayMan.RemoveOverlay(_overlay); + } + } + } + + public override void Shutdown() + { + base.Shutdown(); + _overlayMan.RemoveOverlay(); + } + + private void OnDisableGlimmerShaderChanged(bool enabled) + { + _cvarDisabled = enabled; + if (enabled) + _overlayMan.RemoveOverlay(_overlay); + else if (_overlay.ActualGlimmerLevel > 700) + _overlayMan.AddOverlay(_overlay); + } + +} diff --git a/Content.Shared/Nyanotrasen/Psionics/Glimmer/GlimmerSystem.cs b/Content.Shared/Nyanotrasen/Psionics/Glimmer/GlimmerSystem.cs index 561b2202f9..56e4a4e5d6 100644 --- a/Content.Shared/Nyanotrasen/Psionics/Glimmer/GlimmerSystem.cs +++ b/Content.Shared/Nyanotrasen/Psionics/Glimmer/GlimmerSystem.cs @@ -15,7 +15,15 @@ namespace Content.Shared.Psionics.Glimmer public int Glimmer { get { return _glimmer; } - set { _glimmer = _enabled ? Math.Clamp(value, 0, 1000) : 0; } + set + { + var newGlimmer = _enabled ? Math.Clamp(value, 0, 1000) : 0; + if (_glimmer == newGlimmer) + return; + + _glimmer = newGlimmer; + RaiseNetworkEvent(new GlimmerChangedEvent(_glimmer)); + } } private bool _enabled; public override void Initialize() @@ -62,4 +70,15 @@ namespace Content.Shared.Psionics.Glimmer Dangerous, Critical, } + + [Serializable, NetSerializable] + public sealed class GlimmerChangedEvent : EntityEventArgs + { + public int Glimmer { get; } + + public GlimmerChangedEvent(int glimmer) + { + Glimmer = glimmer; + } + } } diff --git a/Content.Shared/_DV/CCVars/DCCVars.cs b/Content.Shared/_DV/CCVars/DCCVars.cs index db1c90b502..2cbfb5c0f7 100644 --- a/Content.Shared/_DV/CCVars/DCCVars.cs +++ b/Content.Shared/_DV/CCVars/DCCVars.cs @@ -94,6 +94,12 @@ public sealed partial class DCCVars public static readonly CVarDef NoVisionFilters = CVarDef.Create("accessibility.no_vision_filters", true, CVar.CLIENTONLY | CVar.ARCHIVE); + /// + /// Disables the fullscreen shader at 700+ glimmer. + /// + public static readonly CVarDef DisableGlimmerShader = + CVarDef.Create("accessibility.disable_glimmer_shader", false, CVar.CLIENTONLY | CVar.ARCHIVE); + /// /// Whether the Shipyard is enabled. /// diff --git a/Content.Shared/_DV/Overlays/GlimmerOverlayComponent.cs b/Content.Shared/_DV/Overlays/GlimmerOverlayComponent.cs new file mode 100644 index 0000000000..1338c8ef9d --- /dev/null +++ b/Content.Shared/_DV/Overlays/GlimmerOverlayComponent.cs @@ -0,0 +1,6 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._DV.Overlays; + +[RegisterComponent, NetworkedComponent] +public sealed partial class GlimmerOverlayComponent : Component; diff --git a/Resources/Locale/en-US/_DV/escape-menu/options-menu.ftl b/Resources/Locale/en-US/_DV/escape-menu/options-menu.ftl index 68bb35fa5f..71e4d1c8a3 100644 --- a/Resources/Locale/en-US/_DV/escape-menu/options-menu.ftl +++ b/Resources/Locale/en-US/_DV/escape-menu/options-menu.ftl @@ -2,6 +2,7 @@ ui-options-tab-deltav = DeltaV ui-options-general-forknotice = Note: These settings are fork-specific and might not apply on other servers. ui-options-no-filters = Disable species vision filters +ui-options-disable-glimmer-effect = Disable high glimmer shader effect ## DeltaV NanoChat keybinds ui-options-header-nano-chat = NanoChat diff --git a/Resources/Prototypes/_DV/Shaders/highglimmer.yml b/Resources/Prototypes/_DV/Shaders/highglimmer.yml new file mode 100644 index 0000000000..f5eb048782 --- /dev/null +++ b/Resources/Prototypes/_DV/Shaders/highglimmer.yml @@ -0,0 +1,4 @@ +- type: shader + id: HighGlimmer + kind: source + path: "/Textures/_DV/Shaders/highglimmer.swsl" diff --git a/Resources/Textures/_DV/Shaders/highglimmer.swsl b/Resources/Textures/_DV/Shaders/highglimmer.swsl new file mode 100644 index 0000000000..bf4b129578 --- /dev/null +++ b/Resources/Textures/_DV/Shaders/highglimmer.swsl @@ -0,0 +1,49 @@ +// Shader by Xor, taken and modified from https://www.shadertoy.com/view/3fKSzc. +// Licensed under CC BY-NC-SA 3.0: https://creativecommons.org/licenses/by-nc-sa/3.0/deed.en + +const highp float TimeScale = 0.2; + +uniform highp float size = 1; + +void fragment() { + vec2 iResolution = vec2(1.0); + vec2 I = UV * iResolution; + + //Raymarch depth + float z = 0.0; + //Step distance + float d = 0.0; + //Raymarch iterator + float i = 0.0; + //Animation time + float t = TIME * TimeScale; + + vec4 O = vec4(0.0); + + //Clear fragColor and raymarch (some amount of) steps + while (i++ < 25) { + // sample point (from ray direction) + vec3 p = z * normalize(vec3(I + I, 0.0) - iResolution.xyx) + 0.1; + + // polar coordinates + p = vec3(atan(p.y, p.x) * 2.0, p.z / (3.0*(3.0-size)), length(p.xy) - 4.5 - z * (0.5 * 2.8-size)); + + // apply turbulence + d = 0.0; + float j = 0.0; + while (++j < 9.0) + p += sin(p.yzx * j - t + 0.2 * i) / j; + + // distance to cylinder and waves + d = 0.2 * length(vec4(p.z, 0.1 * cos(p * 3.0) - 0.1)); + z += d; + + // coloring and brightness + O += (1.0 + cos(i * 0.7 + vec4(6.0, 1.0, 2.0, 0.0))) / d / i; + } + + // tanh tonemap + O = tanh(O * O / 900.0); + + COLOR = O; +}