diff --git a/Content.Client/Singularity/SingularityOverlay.cs b/Content.Client/Singularity/SingularityOverlay.cs index e71b6e96b8..bf91676b22 100644 --- a/Content.Client/Singularity/SingularityOverlay.cs +++ b/Content.Client/Singularity/SingularityOverlay.cs @@ -17,10 +17,12 @@ public sealed class SingularityOverlay : Overlay, IEntityEventSubscriber /// Maximum number of distortions that can be shown on screen at a time. /// If this value is changed, the shader itself also needs to be updated. /// - public const int MaxCount = 5; + public const int MaxCount = 32; private const float MaxDistance = 20f; + private const float MaxDeformation = 8.0f; + public override OverlaySpace Space => OverlaySpace.WorldSpace; public override bool RequestScreenTexture => true; @@ -38,6 +40,7 @@ public SingularityOverlay() private readonly Vector2[] _positions = new Vector2[MaxCount]; private readonly float[] _intensities = new float[MaxCount]; private readonly float[] _falloffPowers = new float[MaxCount]; + private readonly bool[] _haveEventHorizons = new bool[MaxCount]; private int _count = 0; protected override bool BeforeDraw(in OverlayDrawArgs args) @@ -68,6 +71,7 @@ protected override bool BeforeDraw(in OverlayDrawArgs args) _positions[_count] = tempCoords; _intensities[_count] = distortion.Intensity; _falloffPowers[_count] = distortion.FalloffPower; + _haveEventHorizons[_count] = distortion.HasEventHorizon; _count++; if (_count == MaxCount) @@ -87,6 +91,8 @@ protected override void Draw(in OverlayDrawArgs args) _shader?.SetParameter("position", _positions); _shader?.SetParameter("intensity", _intensities); _shader?.SetParameter("falloffPower", _falloffPowers); + _shader?.SetParameter("hasEventHorizon", _haveEventHorizons); + _shader?.SetParameter("maxDeformation", MaxDeformation); _shader?.SetParameter("SCREEN_TEXTURE", ScreenTexture); var worldHandle = args.WorldHandle; @@ -128,10 +134,16 @@ private void OnProjectFromScreenToMap(ref PixelToMapEvent args) if (distance >= maxDistance) deformation = 0.0f; else + { deformation *= 1.0f - MathF.Pow(distance / maxDistance, 4.0f); - if (deformation > 0.8) - deformation = MathF.Pow(deformation, 0.3f); + if (_haveEventHorizons[i] && _intensities[i] > 0.0f) + { + deformation += MathF.Pow(deformation / MaxDeformation, 32.0f); + if (deformation > 2.0f * MaxDeformation) + deformation = 0.0f; + } + } finalCoords -= delta * deformation; } diff --git a/Content.Shared/Singularity/Components/SingularityDistortionComponent.cs b/Content.Shared/Singularity/Components/SingularityDistortionComponent.cs index 1382dd45f4..95e349601e 100644 --- a/Content.Shared/Singularity/Components/SingularityDistortionComponent.cs +++ b/Content.Shared/Singularity/Components/SingularityDistortionComponent.cs @@ -13,5 +13,12 @@ public sealed partial class SingularityDistortionComponent : Component [DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public float FalloffPower = MathF.Sqrt(2f); + + /// + /// Whether this Distortion should have a visible pitch-black region in the center. True for bodies with + /// extreme gravity, like the singularity. + /// + [DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] + public bool HasEventHorizon; } } diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml index eddf92c5ae..1f29ff0be9 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml @@ -1217,12 +1217,11 @@ - type: Sprite sprite: Objects/Fun/toys.rsi state: singularitytoy - - type: Icon - sprite: Objects/Fun/toys.rsi - state: singularitytoy + color: transparent - type: SingularityDistortion intensity: 2000 falloffPower: 2.6 + hasEventHorizon: true - type: Item size: Normal sprite: Objects/Fun/toys.rsi diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml index 53c53fb5dc..7034d5b9b5 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml @@ -4,11 +4,6 @@ description: A mesmerizing swirl of darkness that sucks in everything. If it's moving towards you, run. components: - type: Clickable - - type: AmbientSound - volume: -4 - range: 14 - sound: - path: /Audio/Effects/singularity.ogg - type: Physics bodyType: Dynamic bodyStatus: InAir @@ -54,12 +49,10 @@ - type: SingularityDistortion falloffPower: 2.529822 intensity: 3645 + hasEventHorizon: true - type: RadiationSource slope: 0.2 # its emit really far away intensity: 2 - - type: PointLight - enabled: true - radius: 10 - type: Appearance - type: GuideHelp guides: [ Singularity, Power ] # uhhh.. I would hoped they'd have read the manual before ever getting in viewing distance... @@ -67,36 +60,4 @@ follow: true location: "! сингулярность" - type: Sprite - sprite: Structures/Power/Generation/Singularity/singularity_1.rsi - shader: unshaded - layers: - - map: [ "VisualLevel" ] - state: singularity_1 - - type: GenericVisualizer - visuals: - enum.SingularityAppearanceKeys.Singularity: - VisualLevel: - 1: - sprite: Structures/Power/Generation/Singularity/singularity_1.rsi - state: singularity_1 - scale: 1.0,1.0 - 2: - sprite: Structures/Power/Generation/Singularity/singularity_2.rsi - state: singularity_2 - scale: 1.0,1.0 - 3: - sprite: Structures/Power/Generation/Singularity/singularity_3.rsi - state: singularity_3 - scale: 1.0,1.0 - 4: - sprite: Structures/Power/Generation/Singularity/singularity_4.rsi - state: singularity_4 - scale: 1.0,1.0 - 5: - sprite: Structures/Power/Generation/Singularity/singularity_5.rsi - state: singularity_5 - scale: 1.5,1.5 - 6: - sprite: Structures/Power/Generation/Singularity/singularity_6.rsi - state: singularity_6 - scale: .9,.9 + sprite: null diff --git a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml index f675b2d2c8..61e567e865 100644 --- a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml +++ b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml @@ -145,8 +145,8 @@ - type: CanMoveInAir - type: RandomWalk - type: SingularityDistortion - intensity: 1000 - falloffPower: 2.7 + intensity: 200 + falloffPower: 1.7 - type: entity id: AnomalyElectricity diff --git a/Resources/Textures/Shaders/singularity.swsl b/Resources/Textures/Shaders/singularity.swsl index 609a4b3b10..f9ff496bdf 100644 --- a/Resources/Textures/Shaders/singularity.swsl +++ b/Resources/Textures/Shaders/singularity.swsl @@ -4,11 +4,13 @@ uniform sampler2D SCREEN_TEXTURE; uniform highp vec2 renderScale; uniform highp float maxDistance; uniform lowp int count; +uniform highp float maxDeformation; -uniform highp float[5] falloffPower; -uniform highp float[5] intensity; -uniform highp vec2[5] position; -// the `5`s in the array lengths correspond to the upper limit on the simultaneous distortion sources that can be present on screen at a time. +uniform highp float[32] falloffPower; +uniform highp float[32] intensity; +uniform highp vec2[32] position; +uniform bool[32] hasEventHorizon; +// The array lengths correspond to the upper limit on the simultaneous distortion sources that can be present on screen at a time. // If you want to change this, make sure to change all of them here, in the for loop, and, in whatever overlay assigns the uniforms // (apparently #define is an unknown preprocessor directive) @@ -18,28 +20,36 @@ void fragment() { highp vec2 delta; highp float distance; highp float deformation; - - for (int i = 0; i < 5 && i < count; i++) { - + lowp float brightnessFactor = 1.0; + lowp float cumulativeBrightnessFactor = 1.0; + + for (int i = 0; i < 32 && i < count; i++) { + delta = FRAGCOORD.xy - position[i]; - distance = length(delta / renderScale); + distance = length(delta / renderScale); deformation = intensity[i] / pow(distance, falloffPower[i]); - + // ensure deformation goes to zero at max distance // avoids long-range single-pixel shifts that are noticeable when leaving PVS. - if (distance >= maxDistance) { deformation = 0.0; } else { - deformation *= (1.0 - pow(distance/maxDistance, 4.0)); + deformation *= (1.0 - pow(distance / maxDistance, 4.0)); + + if (hasEventHorizon[i] && intensity[i] > 0.0) { + deformation += pow(deformation / maxDeformation, 32.0); + + brightnessFactor = clamp(-0.75 * deformation + 10.0, 0.0, 1.0); + cumulativeBrightnessFactor *= brightnessFactor; + } } - - if(deformation > 0.8) - deformation = pow(deformation, 0.3); finalCoords -= deformation * delta; } - - COLOR = zTextureSpec(SCREEN_TEXTURE, finalCoords*SCREEN_PIXEL_SIZE ); + + lowp vec4 color = zTextureSpec(SCREEN_TEXTURE, finalCoords * SCREEN_PIXEL_SIZE); + color.rgb *= cumulativeBrightnessFactor; + + COLOR = color; }