Additive lighting (#685)

* Additive lighting

* adds options for all your optional needs

* one last tiny adjustment before we hit the create pr button

* spaghetti condensing

* add ccvar

* overlight correction

* fix requested changes

* cvar fix

* last fix

* nice

---------

Co-authored-by: deathride58 <deathride58@users.noreply.github.com>
Co-authored-by: MetalSage <metalsage.official@gmail.com>
Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
Co-authored-by: Ed <edwardxperia2000@gmail.com>
This commit is contained in:
MetalSage
2025-01-12 14:33:06 +04:00
committed by GitHub
parent a6847c08e8
commit 89b9a5c1fe
13 changed files with 168 additions and 12 deletions

View File

@@ -12,6 +12,7 @@ using Content.Client.IoC;
using Content.Client.Launcher;
using Content.Client.Lobby;
using Content.Client.MainMenu;
using Content.Client.Overlays;
using Content.Client.Parallax.Managers;
using Content.Client.Players.PlayTimeTracking;
using Content.Client.Radiation.Overlays;
@@ -159,6 +160,7 @@ namespace Content.Client.Entry
_parallaxManager.LoadDefaultParallax();
_overlayManager.AddOverlay(new CP14BasePostProcessOverlay()); // CP14-PostProcess
_overlayManager.AddOverlay(new SingularityOverlay());
_overlayManager.AddOverlay(new RadiationPulseOverlay());
_chatManager.Initialize();

View File

@@ -16,11 +16,12 @@
<Label Text="{Loc 'cp14-ui-options-main-graphics-label'}"
StyleClasses="LabelKeyText"/>
<!-- CP14 Wave shader settings -->
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'cp14-ui-options-main-graphics-wave-shader'}" Margin="0 0 4 0"/>
<CheckBox Name="WaveShaderEnabled"/>
</BoxContainer>
<CheckBox Name="WaveShaderEnabled"
Text="{Loc 'cp14-ui-options-main-graphics-wave-shader'}"/>
<!-- TODO: Wave shader tooltip -->
<CheckBox Name="PostProcessCheckBox"
Text="{Loc 'cp14-ui-options-postprocess'}"
ToolTip="{Loc 'cp14-ui-options-postprocess-tooltip'}"/>
</BoxContainer>
</ScrollContainer>

View File

@@ -13,6 +13,7 @@ public sealed partial class CP14OptionsMenuMainTab : Control
RobustXamlLoader.Load(this);
Control.AddOptionCheckBox(CP14ConfigVars.WaveShaderEnabled, WaveShaderEnabled);
Control.AddOptionCheckBox(CP14ConfigVars.PostProcess, PostProcessCheckBox);
Control.Initialize();
}

View File

@@ -0,0 +1,77 @@
using Content.Shared._CP14.Configuration;
using System.Numerics;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Enums;
using Robust.Shared.Graphics;
using Robust.Shared.Physics;
using Robust.Shared.Prototypes;
namespace Content.Client.Overlays;
// This overlay serves as the foundational post processing overlay.
// Ideally, for performance reasons, post processing designed to be present at all times, such as additive light blending or tonemapping, should be done as part of a single shader pass.
public sealed class CP14BasePostProcessOverlay : Overlay
{
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly ILightManager _lightManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override bool RequestScreenTexture => true;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
private readonly ShaderInstance _basePostProcessShader;
public CP14BasePostProcessOverlay()
{
IoCManager.InjectDependencies(this);
_basePostProcessShader = _prototypeManager.Index<ShaderPrototype>("BasePostProcess").InstanceUnique();
}
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
if (!_configManager.GetCVar(CP14ConfigVars.PostProcess))
return false;
if (!_entityManager.TryGetComponent(_playerManager.LocalSession?.AttachedEntity, out EyeComponent? eyeComp))
return false;
if (args.Viewport.Eye != eyeComp.Eye)
return false;
if (!_lightManager.Enabled || !eyeComp.Eye.DrawLight)
return false;
var playerEntity = _playerManager.LocalSession?.AttachedEntity;
if (playerEntity == null)
return false;
return true;
}
protected override void Draw(in OverlayDrawArgs args)
{
if (ScreenTexture == null)
return;
if (args.Viewport.Eye == null)
return;
var playerEntity = _playerManager.LocalSession?.AttachedEntity;
var worldHandle = args.WorldHandle;
var viewport = args.WorldBounds;
_basePostProcessShader.SetParameter("SCREEN_TEXTURE", ScreenTexture);
_basePostProcessShader.SetParameter("LIGHT_TEXTURE", args.Viewport.LightRenderTarget.Texture);
_basePostProcessShader.SetParameter("Zoom", args.Viewport.Eye.Zoom.X);
worldHandle.UseShader(_basePostProcessShader);
worldHandle.DrawRect(viewport, Color.White);
worldHandle.UseShader(null);
}
}

View File

@@ -8,4 +8,12 @@ public sealed class CP14ConfigVars : CVars
{
public static readonly CVarDef<bool>
WaveShaderEnabled = CVarDef.Create("cp14_rendering.wave_shader_enabled", true, CVar.CLIENT | CVar.ARCHIVE);
/// <summary>
/// Toggle for non-gameplay-affecting or otherwise status indicative post-process effects, such additive lighting.
/// In the future, this could probably be turned into an enum that allows only disabling more expensive post-process shaders.
/// However, for now (mid-July of 2024), this only applies specifically to a particularly cheap shader: additive lighting.
/// </summary>
public static readonly CVarDef<bool>
PostProcess = CVarDef.Create("cp14_graphics.post_process", true, CVar.CLIENTONLY | CVar.ARCHIVE);
}

View File

@@ -5,4 +5,12 @@ cp14-ui-options-tab-main = CP14
## Graphics
cp14-ui-options-main-graphics-label = Graphics
cp14-ui-options-main-graphics-wave-shader = Wave shader:
cp14-ui-options-main-graphics-wave-shader = Wave shader
cp14-ui-options-postprocess = Cosmetic Post-processing
cp14-ui-options-postprocess-tooltip =
When enabled, cosmetic post-processing effects such as
additive lighting will be present. This does not control
post-process effects that affect the game or otherwise
carry some form of gameplay-related meaning.

View File

@@ -5,4 +5,12 @@ cp14-ui-options-tab-main = CP14
## Graphics
cp14-ui-options-main-graphics-label = Графика
cp14-ui-options-main-graphics-wave-shader = Шейдер покачивания (Wave shader):
cp14-ui-options-main-graphics-wave-shader = Шейдер покачивания
cp14-ui-options-postprocess = Косметическая постобработка
cp14-ui-options-postprocess-tooltip =
Если эта функция включена, то будут присутствовать косметические эффекты постобработки,
такие как аддитивное освещение. Это не управляет эффеками постобработки, которые
влияют на игру или иным образом не контролирует эффекты постобработки, которые
влияют на игру или имеют какое-то значение для игрового процесса.

View File

@@ -108,4 +108,4 @@
- type: shader
id: Hologram
kind: source
path: "/Textures/Shaders/hologram.swsl"
path: "/Textures/Shaders/hologram.swsl"

View File

@@ -69,7 +69,7 @@
drawdepth: Mobs
offset: 0,0.9
- type: PointLight
energy: 5
energy: 2.5
radius: 8
- type: entity

View File

@@ -90,7 +90,7 @@
shader: unshaded
- type: PointLight
color: "#e67c34"
energy: 5
energy: 2
radius: 8
- type: AmbientSound
enabled: true

View File

@@ -20,7 +20,7 @@
map: [ "light" ]
visible: false
- type: PointLight
energy: 2
energy: 1
radius: 8
color: "#b2ceeb"
enabled: false

View File

@@ -1,4 +1,21 @@
- type: shader
id: Wave
kind: source
path: "/Textures/_CP14/Shaders/wave.swsl"
path: "/Textures/_CP14/Shaders/wave.swsl"
# Base post-processing
- type: shader
id: BasePostProcess
kind: source
path: "/Textures/_CP14/Shaders/base_postprocess.swsl"
params:
CircleRadius: 420.0
CircleMinDist: 0.0
CirclePow: 1.0
CircleMax: 4.0
CircleMult: 0.25
FalloffClampMin: 0.075
FalloffClampMax: 1.0
FalloffStrength: 0.75
FalloffPow: 3.0
HDR: 1.5

View File

@@ -0,0 +1,34 @@
//Boilerplate
uniform sampler2D SCREEN_TEXTURE;
uniform sampler2D LIGHT_TEXTURE;
uniform highp float Zoom;
//Variables for controlling the falloff of the additive lighting effect.
uniform highp float CircleRadius; //= 420.0;
uniform highp float CircleMinDist; //= 0.0;
uniform highp float CirclePow; //= 1.0;
uniform highp float CircleMax; //= 4.0;
uniform highp float CircleMult; //= 0.25;
uniform highp float FalloffClampMin; //= 0.075;
uniform highp float FalloffClampMax; //= 1.0;
uniform highp float FalloffStrength; //= 0.75;
uniform highp float FalloffPow; //= 3.0;
uniform highp float HDR; //= 1.5;
void fragment() {
COLOR = zTextureSpec(SCREEN_TEXTURE, Pos);
highp vec2 aspect = vec2(1.0/SCREEN_PIXEL_SIZE.x, 1.0/SCREEN_PIXEL_SIZE.y);
highp float actualZoom = Zoom;
highp float circle = clamp(zCircleGradient(aspect, FRAGCOORD.xy, CircleMax, CircleRadius / actualZoom, CircleMinDist / actualZoom, CirclePow) * CircleMult, FalloffClampMin, FalloffClampMax);
highp vec3 lightsampleraw = texture2D(LIGHT_TEXTURE, Pos).rgb;
lightsampleraw = smoothstep(0.0, HDR, lightsampleraw);
highp float graylight = max(zGrayscale(lightsampleraw) - max((1.0 - circle) * FalloffStrength, 0.0), 0.0);
graylight = pow(graylight, FalloffPow);
highp vec3 lightsample = lightsampleraw * vec3(graylight);
COLOR.rgb = COLOR.rgb + lightsample;
}