Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

outlines for the stealth shader #1150

Merged
merged 9 commits into from
Dec 30, 2024
Merged
35 changes: 33 additions & 2 deletions Content.Client/Stealth/StealthSystem.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Content.Client.Administration.Managers;
using Content.Client.Interactable.Components;
using Content.Client.StatusIcon;
using Content.Shared.Ghost;
using Content.Shared.Stealth;
using Content.Shared.Stealth.Components;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Shared.Prototypes;

namespace Content.Client.Stealth;
Expand All @@ -12,14 +14,16 @@ public sealed class StealthSystem : SharedStealthSystem
{
[Dependency] private readonly IPrototypeManager _protoMan = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IClientAdminManager _adminManager = default!;

private ShaderInstance _shader = default!;

public override void Initialize()
{
base.Initialize();

_shader = _protoMan.Index<ShaderPrototype>("Stealth").InstanceUnique();
_shader = _protoMan.Index<ShaderPrototype>("AccesibleFullStealth").InstanceUnique();

SubscribeLocalEvent<StealthComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<StealthComponent, ComponentStartup>(OnStartup);
Expand Down Expand Up @@ -86,6 +90,33 @@ private void OnShaderRender(EntityUid uid, StealthComponent component, BeforePos
reference.X = -reference.X;
var visibility = GetVisibility(uid, component);

//imp special - show an outline for people that should see it, goes along with complete invisibility
//includes the entity with the component, any admins & any ghosts
//todo want this to check for if the player's entity is inside a container as well
_shader.SetParameter("ShowOutline", false); //make sure it's always false by default

bool isAdmin = false;
bool isCorrectSession = false;
bool isGhost = false;
bool isInContainer = false;

if (_playerManager.LocalSession != null)
{
if (_playerManager.TryGetSessionByEntity(uid, out var playerSession))
{
isCorrectSession = playerSession.UserId == _playerManager.LocalSession.UserId;
}

isAdmin = _adminManager.IsAdmin();
isGhost = HasComp<GhostComponent>(_playerManager.LocalSession.AttachedEntity);
}

if (isAdmin || isCorrectSession || isGhost || isInContainer)
{
_shader.SetParameter("ShowOutline", true);
}
//imp special end

// actual visual visibility effect is limited to +/- 1.
visibility = Math.Clamp(visibility, -1f, 1f);

Expand Down
4 changes: 4 additions & 0 deletions Resources/Prototypes/_Impstation/Shaders/shaders.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- type: shader
id: AccesibleFullStealth
ruddygreat marked this conversation as resolved.
Show resolved Hide resolved
kind: source
path: "/Textures/_Impstation/Shaders/accesible_full_stealth.swsl"
72 changes: 72 additions & 0 deletions Resources/Textures/_Impstation/Shaders/accesible_full_stealth.swsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
light_mode unshaded;

uniform sampler2D SCREEN_TEXTURE;
uniform highp float visibility; // number between -1 and 1
uniform bool ShowOutline;

uniform highp float outline_width = 2.0;
uniform highp vec4 outline_color = vec4(0.0,1.0,0.0,0.33);
uniform bool outline_fullbright = false;
uniform highp float light_boost = 4.0;
uniform highp float light_gamma = 1.0;
uniform highp float light_whitepoint = 1.0;

void fragment() {
highp vec4 spriteCol = zTexture(UV);
highp vec4 outlineCol = getOutlineCol();
highp float clampedVis = clamp(visibility, 0, 1);

if (outlineCol.a > 0.1 && ShowOutline) {
COLOR.rgb = outlineCol.rgb;
COLOR.a = outlineCol.a * (1 - clampedVis);
} else {
COLOR.rgb = spriteCol.rgb;
COLOR.a = spriteCol.a * clampedVis;
}
}

highp vec4 getOutlineCol() {
highp vec4 col = zTexture(UV);
highp vec2 ps = TEXTURE_PIXEL_SIZE;
highp float a;
highp float maxa = col.a;
highp float mina = col.a;

// note: these bypass zTexture because only alpha is queried.
a = texture2D(TEXTURE, UV + vec2(0.0, -outline_width)*ps).a;
maxa = max(a, maxa);
mina = min(a, mina);

a = texture2D(TEXTURE, UV + vec2(-outline_width, -outline_width)*ps).a;
maxa = max(a, maxa);
mina = min(a, mina);

a = texture2D(TEXTURE, UV + vec2(0.0, outline_width)*ps).a;
maxa = max(a, maxa);
mina = min(a, mina);

a = texture2D(TEXTURE, UV + vec2(outline_width, -outline_width)*ps).a;
maxa = max(a, maxa);
mina = min(a, mina);

a = texture2D(TEXTURE, UV + vec2(-outline_width,0.0)*ps).a;
maxa = max(a, maxa);
mina = min(a, mina);

a = texture2D(TEXTURE, UV + vec2(-outline_width, outline_width)*ps).a;
maxa = max(a, maxa);
mina = min(a, mina);

a = texture2D(TEXTURE, UV + vec2(outline_width, 0.0)*ps).a;
maxa = max(a, maxa);
mina = min(a, mina);

a = texture2D(TEXTURE, UV + vec2(outline_width, outline_width)*ps).a;
maxa = max(a, maxa);
mina = min(a, mina);

//todo figure out how to make this not look like ass
//the original outline shader has some dark magic in it, maybe move that up to the main method?

return vec4(outline_color.rgb, maxa - col.a);
}
Loading