improve noir glasses shader (#37996)
* improve noir glasses shader * tweak values
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Player;
|
|
||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
@@ -7,9 +6,7 @@ namespace Content.Client.Overlays;
|
|||||||
|
|
||||||
public sealed partial class BlackAndWhiteOverlay : Overlay
|
public sealed partial class BlackAndWhiteOverlay : Overlay
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
|
||||||
|
|
||||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||||
public override bool RequestScreenTexture => true;
|
public override bool RequestScreenTexture => true;
|
||||||
@@ -22,17 +19,6 @@ public sealed partial class BlackAndWhiteOverlay : Overlay
|
|||||||
ZIndex = 10; // draw this over the DamageOverlay, RainbowOverlay etc.
|
ZIndex = 10; // draw this over the DamageOverlay, RainbowOverlay etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool BeforeDraw(in OverlayDrawArgs args)
|
|
||||||
{
|
|
||||||
if (!_entityManager.TryGetComponent(_playerManager.LocalEntity, out EyeComponent? eyeComp))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (args.Viewport.Eye != eyeComp.Eye)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Draw(in OverlayDrawArgs args)
|
protected override void Draw(in OverlayDrawArgs args)
|
||||||
{
|
{
|
||||||
if (ScreenTexture == null)
|
if (ScreenTexture == null)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Content.Shared.Inventory.Events;
|
using Content.Shared.Inventory.Events;
|
||||||
using Content.Shared.Overlays;
|
using Content.Shared.Overlays;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Player;
|
|
||||||
|
|
||||||
namespace Content.Client.Overlays;
|
namespace Content.Client.Overlays;
|
||||||
|
|
||||||
|
|||||||
33
Content.Client/Overlays/NoirOverlay.cs
Normal file
33
Content.Client/Overlays/NoirOverlay.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Client.Overlays;
|
||||||
|
|
||||||
|
public sealed partial class NoirOverlay : Overlay
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
|
||||||
|
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||||
|
public override bool RequestScreenTexture => true;
|
||||||
|
private readonly ShaderInstance _noirShader;
|
||||||
|
|
||||||
|
public NoirOverlay()
|
||||||
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
_noirShader = _prototypeManager.Index<ShaderPrototype>("Noir").InstanceUnique();
|
||||||
|
ZIndex = 9; // draw this over the DamageOverlay, RainbowOverlay etc, but before the black and white shader
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(in OverlayDrawArgs args)
|
||||||
|
{
|
||||||
|
if (ScreenTexture == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var handle = args.WorldHandle;
|
||||||
|
_noirShader.SetParameter("SCREEN_TEXTURE", ScreenTexture);
|
||||||
|
handle.UseShader(_noirShader);
|
||||||
|
handle.DrawRect(args.WorldBounds, Color.White);
|
||||||
|
handle.UseShader(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
33
Content.Client/Overlays/NoirOverlaySystem.cs
Normal file
33
Content.Client/Overlays/NoirOverlaySystem.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using Content.Shared.Inventory.Events;
|
||||||
|
using Content.Shared.Overlays;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
|
||||||
|
namespace Content.Client.Overlays;
|
||||||
|
|
||||||
|
public sealed partial class NoirOverlaySystem : EquipmentHudSystem<NoirOverlayComponent>
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IOverlayManager _overlayMan = default!;
|
||||||
|
|
||||||
|
private NoirOverlay _overlay = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
_overlay = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateInternal(RefreshEquipmentHudEvent<NoirOverlayComponent> component)
|
||||||
|
{
|
||||||
|
base.UpdateInternal(component);
|
||||||
|
|
||||||
|
_overlayMan.AddOverlay(_overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DeactivateInternal()
|
||||||
|
{
|
||||||
|
base.DeactivateInternal();
|
||||||
|
|
||||||
|
_overlayMan.RemoveOverlay(_overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -85,6 +85,7 @@ public partial class InventorySystem
|
|||||||
SubscribeLocalEvent<InventoryComponent, RefreshEquipmentHudEvent<ShowSyndicateIconsComponent>>(RefRelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, RefreshEquipmentHudEvent<ShowSyndicateIconsComponent>>(RefRelayInventoryEvent);
|
||||||
SubscribeLocalEvent<InventoryComponent, RefreshEquipmentHudEvent<ShowCriminalRecordIconsComponent>>(RefRelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, RefreshEquipmentHudEvent<ShowCriminalRecordIconsComponent>>(RefRelayInventoryEvent);
|
||||||
SubscribeLocalEvent<InventoryComponent, RefreshEquipmentHudEvent<BlackAndWhiteOverlayComponent>>(RefRelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, RefreshEquipmentHudEvent<BlackAndWhiteOverlayComponent>>(RefRelayInventoryEvent);
|
||||||
|
SubscribeLocalEvent<InventoryComponent, RefreshEquipmentHudEvent<NoirOverlayComponent>>(RefRelayInventoryEvent);
|
||||||
|
|
||||||
SubscribeLocalEvent<InventoryComponent, GetVerbsEvent<EquipmentVerb>>(OnGetEquipmentVerbs);
|
SubscribeLocalEvent<InventoryComponent, GetVerbsEvent<EquipmentVerb>>(OnGetEquipmentVerbs);
|
||||||
SubscribeLocalEvent<InventoryComponent, GetVerbsEvent<InnateVerb>>(OnGetInnateVerbs);
|
SubscribeLocalEvent<InventoryComponent, GetVerbsEvent<InnateVerb>>(OnGetInnateVerbs);
|
||||||
|
|||||||
10
Content.Shared/Overlays/NoirOverlayComponent.cs
Normal file
10
Content.Shared/Overlays/NoirOverlayComponent.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Overlays;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Makes the entity see everything with a sin city shader (everything in black and white, except red) by adding an overlay.
|
||||||
|
/// When added to a clothing item it will also grant the wearer the same overlay.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
public sealed partial class NoirOverlayComponent : Component;
|
||||||
@@ -281,7 +281,7 @@
|
|||||||
- type: FlashImmunity
|
- type: FlashImmunity
|
||||||
- type: EyeProtection
|
- type: EyeProtection
|
||||||
protectionTime: 5
|
protectionTime: 5
|
||||||
- type: BlackAndWhiteOverlay
|
- type: NoirOverlay
|
||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- HamsterWearable
|
- HamsterWearable
|
||||||
|
|||||||
@@ -47,6 +47,12 @@
|
|||||||
kind: source
|
kind: source
|
||||||
path: "/Textures/Shaders/rainbow.swsl"
|
path: "/Textures/Shaders/rainbow.swsl"
|
||||||
|
|
||||||
|
# sin city effect: everything is greyscale, except red
|
||||||
|
- type: shader
|
||||||
|
id: Noir
|
||||||
|
kind: source
|
||||||
|
path: "/Textures/Shaders/noir.swsl"
|
||||||
|
|
||||||
- type: shader
|
- type: shader
|
||||||
id: CameraStatic
|
id: CameraStatic
|
||||||
kind: source
|
kind: source
|
||||||
|
|||||||
46
Resources/Textures/Shaders/noir.swsl
Normal file
46
Resources/Textures/Shaders/noir.swsl
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// Sin City style shader.
|
||||||
|
// Makes everything black and white, but keeps red colors.
|
||||||
|
|
||||||
|
uniform sampler2D SCREEN_TEXTURE;
|
||||||
|
// Sensitivity, in degrees.
|
||||||
|
const highp float RedHueRange = 5;
|
||||||
|
const highp float MinSaturation = 0.4;
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB
|
||||||
|
highp vec3 rgb2hsv(highp vec3 c) {
|
||||||
|
highp float xMax = max(c.r, max(c.g, c.b));
|
||||||
|
highp float xMin = min(c.r, min(c.g, c.b));
|
||||||
|
highp float delta = xMax - xMin;
|
||||||
|
|
||||||
|
highp float hue = 0.0;
|
||||||
|
if (delta > 0.0) {
|
||||||
|
if (xMax == c.r) {
|
||||||
|
hue = mod((c.g - c.b) / delta, 6.0);
|
||||||
|
} else if (xMax == c.g) {
|
||||||
|
hue = (c.b - c.r) / delta + 2.0;
|
||||||
|
} else {
|
||||||
|
hue = (c.r - c.g) / delta + 4.0;
|
||||||
|
}
|
||||||
|
hue *= 60.0;
|
||||||
|
if (hue < 0.0) hue += 360.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
highp float sat = (xMax == 0.0) ? 0.0 : delta / xMax;
|
||||||
|
return vec3(hue, sat, xMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
highp vec4 color = zTextureSpec(SCREEN_TEXTURE, UV);
|
||||||
|
highp vec3 gray = vec3(zGrayscale(color.rgb));
|
||||||
|
highp vec3 hsv = rgb2hsv(color.rgb);
|
||||||
|
|
||||||
|
// Red is near 0 or 360 in hue
|
||||||
|
bool is_red = hsv.x < RedHueRange || hsv.x > (360.0 - RedHueRange);
|
||||||
|
bool saturated_enough = hsv.y > MinSaturation; // Avoid desaturated pinks/greys
|
||||||
|
|
||||||
|
if (is_red && saturated_enough) {
|
||||||
|
COLOR = color;
|
||||||
|
} else {
|
||||||
|
COLOR = vec4(gray, color.a);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user