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

Planet lighting pre-reqs #5490

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
6 changes: 6 additions & 0 deletions Resources/EnginePrototypes/Shaders/stockshaders.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
kind: canvas
light_mode: unshaded

# Simple mix blend
- type: shader
id: Mix
kind: canvas
blend_mode: Mix

- type: shader
id: shaded
kind: canvas
Expand Down
17 changes: 16 additions & 1 deletion Robust.Client/Graphics/Clyde/Clyde.HLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -423,11 +423,18 @@ private void RenderInRenderTarget(RenderTargetBase rt, Action a, Color? clearCol

var oldTransform = _currentMatrixModel;
var oldScissor = _currentScissorState;
var oldMatrixProj = _currentMatrixProj;
var oldMatrixView = _currentMatrixView;
var oldBoundTarget = _currentBoundRenderTarget;
var oldRenderTarget = _currentRenderTarget;
var oldShader = _queuedShaderInstance;

// Need to get state before flushing render queue in case they modify the original state.
var state = PushRenderStateFull();

// Have to flush the render queue so that all commands finish rendering to the previous framebuffer.
FlushRenderQueue();

var state = PushRenderStateFull();

{
BindRenderTargetFull(RtToLoaded(rt));
Expand All @@ -452,6 +459,14 @@ private void RenderInRenderTarget(RenderTargetBase rt, Action a, Color? clearCol

SetScissorFull(oldScissor);
_currentMatrixModel = oldTransform;

DebugTools.Assert(_currentMatrixModel.Equals(oldTransform));
DebugTools.Assert(_currentScissorState.Equals(oldScissor));
DebugTools.Assert(_currentMatrixProj.Equals(oldMatrixProj));
DebugTools.Assert(oldMatrixView.Equals(_currentMatrixView));
DebugTools.Assert(oldRenderTarget.Equals(_currentRenderTarget));
DebugTools.Assert(oldBoundTarget.Equals(_currentBoundRenderTarget));
DebugTools.Assert(oldShader.Equals(_queuedShaderInstance));
}

private void RenderViewport(Viewport viewport)
Expand Down
79 changes: 57 additions & 22 deletions Robust.Client/Graphics/Clyde/Clyde.LightRendering.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
using TKStencilOp = OpenToolkit.Graphics.OpenGL4.StencilOp;
using Robust.Shared.Physics;
using Robust.Client.ComponentTrees;
using Robust.Shared.Enums;
using Robust.Shared.Graphics;
using Robust.Shared.Prototypes;
using static Robust.Shared.GameObjects.OccluderComponent;
using Robust.Shared.Utility;
using TextureWrapMode = Robust.Shared.Graphics.TextureWrapMode;
Expand Down Expand Up @@ -402,13 +404,43 @@ private void DrawLightsAndFov(Viewport viewport, Box2Rotated worldBounds, Box2 w
CheckGlError();

BindRenderTargetImmediate(RtToLoaded(viewport.LightRenderTarget));
DebugTools.Assert(_currentBoundRenderTarget.TextureHandle.Equals(viewport.LightRenderTarget.Texture.TextureId));
CheckGlError();
GLClearColor(_entityManager.GetComponentOrNull<MapLightComponent>(mapUid)?.AmbientLightColor ?? MapLightComponent.DefaultColor);
GL.ClearStencil(0xFF);
GL.StencilMask(0xFF);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.StencilBufferBit);
CheckGlError();

var oldTarget = _currentRenderTarget;
var oldProj = _currentMatrixProj;
var oldShader = _queuedShaderInstance;
var oldModel = _currentMatrixModel;
var oldScissor = _currentScissorState;
var oldScissoring = _isScissoring;
var state = PushRenderStateFull();

RenderOverlays(viewport, OverlaySpace.BeforeLighting, worldAABB, worldBounds);

if (_lightManager.BlurFactor != 0f && viewport.Eye != null)
BlurLights(viewport, viewport.LightRenderTarget, viewport.Eye, _lightManager.BlurFactor);

// Batching doesn't restore stencil state so we do it here.
// Yes I spent 8 hours across 2 days just to track down this as the problem.
GL.Enable(EnableCap.StencilTest);
GL.ClearStencil(0xFF);
GL.StencilMask(0xFF);
GL.Clear(ClearBufferMask.StencilBufferBit);
PopRenderStateFull(state);
_isStencilling = true;
DebugTools.Assert(oldScissoring.Equals(_isScissoring));
DebugTools.Assert(oldScissor.Equals(_currentScissorState));
DebugTools.Assert(oldModel.Equals(_currentMatrixModel));
DebugTools.Assert(oldShader.Equals(_queuedShaderInstance));
DebugTools.Assert(oldProj.Equals(_currentMatrixProj));
DebugTools.Assert(oldTarget.Equals(_currentRenderTarget));
DebugTools.Assert(_currentBoundRenderTarget.TextureHandle.Equals(viewport.LightRenderTarget.Texture.TextureId));

ApplyLightingFovToBuffer(viewport, eye);

var lightShader = _loadedShaders[_enableSoftShadows ? _lightSoftShaderHandle : _lightHardShaderHandle]
Expand Down Expand Up @@ -515,7 +547,7 @@ private void DrawLightsAndFov(Viewport viewport, Box2Rotated worldBounds, Box2 w
CheckGlError();

if (_cfg.GetCVar(CVars.LightBlur))
BlurLights(viewport, eye);
BlurLights(viewport, viewport.LightRenderTarget, eye);

using (_prof.Group("BlurOntoWalls"))
{
Expand All @@ -531,9 +563,8 @@ private void DrawLightsAndFov(Viewport viewport, Box2Rotated worldBounds, Box2 w
GL.Viewport(0, 0, viewport.Size.X, viewport.Size.Y);
CheckGlError();

Array.Clear(_lightsToRenderList, 0, count);

_lightingReady = true;
Array.Clear(_lightsToRenderList, 0, count);
}

private static bool LightQuery(ref (
Expand Down Expand Up @@ -643,10 +674,14 @@ public int Compare(
return (state.count, expandedBounds);
}

private void BlurLights(Viewport viewport, IEye eye)
private void BlurLights(IClydeViewport viewport, IRenderTarget target, IEye eye, float multiplier = 14f)
{
if (target is not RenderTexture rTexture || viewport is not Viewport rViewport)
return;

using var _ = DebugGroup(nameof(BlurLights));

var state = PushRenderStateFull();
GL.Disable(EnableCap.Blend);
CheckGlError();
CalcScreenMatrices(viewport.Size, out var proj, out var view);
Expand All @@ -655,9 +690,9 @@ private void BlurLights(Viewport viewport, IEye eye)
var shader = _loadedShaders[_lightBlurShaderHandle].Program;
shader.Use();

SetupGlobalUniformsImmediate(shader, viewport.LightRenderTarget.Texture);
SetupGlobalUniformsImmediate(shader, rTexture.Texture);

var size = viewport.LightRenderTarget.Size;
var size = target.Size;
shader.SetUniformMaybe("size", (Vector2)size);
shader.SetUniformTextureMaybe(UniIMainTexture, TextureUnit.Texture0);

Expand All @@ -667,14 +702,13 @@ private void BlurLights(Viewport viewport, IEye eye)
// Initially we're pulling from the light render target.
// So we set it out of the loop so
// _wallBleedIntermediateRenderTarget2 gets bound at the end of the loop body.
SetTexture(TextureUnit.Texture0, viewport.LightRenderTarget.Texture);
SetTexture(TextureUnit.Texture0, rTexture.Texture);

// Have to scale the blurring radius based on viewport size and camera zoom.
const float refCameraHeight = 14;
var facBase = _cfg.GetCVar(CVars.LightBlurFactor);
var cameraSize = eye.Zoom.Y * viewport.Size.Y * (1 / viewport.RenderScale.Y) / EyeManager.PixelsPerMeter;
// 7e-3f is just a magic factor that makes it look ok.
var factor = facBase * (refCameraHeight / cameraSize);
var factor = facBase * (multiplier / cameraSize);

// Multi-iteration gaussian blur.
for (var i = 3; i > 0; i--)
Expand All @@ -683,23 +717,24 @@ private void BlurLights(Viewport viewport, IEye eye)
// Set factor.
shader.SetUniformMaybe("radius", scale);

BindRenderTargetFull(viewport.LightBlurTarget);
BindRenderTargetImmediate(RtToLoaded(rViewport.LightBlurTarget));

// Blur horizontally to _wallBleedIntermediateRenderTarget1.
shader.SetUniformMaybe("direction", Vector2.UnitX);
_drawQuad(Vector2.Zero, viewport.Size, Matrix3x2.Identity, shader);

SetTexture(TextureUnit.Texture0, viewport.LightBlurTarget.Texture);
SetTexture(TextureUnit.Texture0, rViewport.LightBlurTarget.Texture);

BindRenderTargetFull(viewport.LightRenderTarget);
BindRenderTargetImmediate(RtToLoaded(rTexture));

// Blur vertically to _wallBleedIntermediateRenderTarget2.
shader.SetUniformMaybe("direction", Vector2.UnitY);
_drawQuad(Vector2.Zero, viewport.Size, Matrix3x2.Identity, shader);

SetTexture(TextureUnit.Texture0, viewport.LightRenderTarget.Texture);
SetTexture(TextureUnit.Texture0, rTexture.Texture);
}

PopRenderStateFull(state);
GL.Enable(EnableCap.Blend);
CheckGlError();
// We didn't trample over the old _currentMatrices so just roll it back.
Expand Down Expand Up @@ -1135,34 +1170,34 @@ private void RegenLightRts(Viewport viewport)

var lightMapSize = GetLightMapSize(viewport.Size);
var lightMapSizeQuart = GetLightMapSize(viewport.Size, true);
var lightMapColorFormat = _hasGLFloatFramebuffers
? RenderTargetColorFormat.R11FG11FB10F
: RenderTargetColorFormat.Rgba8;
var lightMapSampleParameters = new TextureSampleParameters { Filter = true };

viewport.LightRenderTarget?.Dispose();
viewport.WallMaskRenderTarget?.Dispose();
viewport.WallBleedIntermediateRenderTarget1?.Dispose();
viewport.WallBleedIntermediateRenderTarget2?.Dispose();
var lightMapColorFormat = _hasGLFloatFramebuffers
? RenderTargetColorFormat.R11FG11FB10F
: RenderTargetColorFormat.Rgba8;
var lightMapSampleParameters = new TextureSampleParameters { Filter = true };

viewport.WallMaskRenderTarget = CreateRenderTarget(viewport.Size, RenderTargetColorFormat.R8,
name: $"{viewport.Name}-{nameof(viewport.WallMaskRenderTarget)}");

viewport.LightRenderTarget = CreateRenderTarget(lightMapSize,
new RenderTargetFormatParameters(lightMapColorFormat, hasDepthStencil: true),
lightMapSampleParameters,
viewport.LightRenderTarget = (RenderTexture) CreateLightRenderTarget(lightMapSize,
$"{viewport.Name}-{nameof(viewport.LightRenderTarget)}");

viewport.LightBlurTarget = CreateRenderTarget(lightMapSize,
new RenderTargetFormatParameters(lightMapColorFormat),
lightMapSampleParameters,
$"{viewport.Name}-{nameof(viewport.LightBlurTarget)}");

viewport.WallBleedIntermediateRenderTarget1 = CreateRenderTarget(lightMapSizeQuart, lightMapColorFormat,
viewport.WallBleedIntermediateRenderTarget1 = CreateRenderTarget(lightMapSizeQuart,
new RenderTargetFormatParameters(lightMapColorFormat),
lightMapSampleParameters,
$"{viewport.Name}-{nameof(viewport.WallBleedIntermediateRenderTarget1)}");

viewport.WallBleedIntermediateRenderTarget2 = CreateRenderTarget(lightMapSizeQuart, lightMapColorFormat,
viewport.WallBleedIntermediateRenderTarget2 = CreateRenderTarget(lightMapSizeQuart,
new RenderTargetFormatParameters(lightMapColorFormat),
lightMapSampleParameters,
$"{viewport.Name}-{nameof(viewport.WallBleedIntermediateRenderTarget2)}");
}
Expand Down
29 changes: 26 additions & 3 deletions Robust.Client/Graphics/Clyde/Clyde.RenderTargets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ private readonly ConcurrentQueue<ClydeHandle> _renderTargetDisposeQueue
// It, like _mainWindowRenderTarget, is initialized in Clyde's constructor
private LoadedRenderTarget _currentBoundRenderTarget;


public IRenderTexture CreateLightRenderTarget(Vector2i size, string? name = null, bool depthStencil = true)
{
var lightMapColorFormat = _hasGLFloatFramebuffers
? RTCF.R11FG11FB10F
: RTCF.Rgba8;
var lightMapSampleParameters = new TextureSampleParameters { Filter = true };

return CreateRenderTarget(size,
new RenderTargetFormatParameters(lightMapColorFormat, hasDepthStencil: depthStencil),
lightMapSampleParameters,
name: name);
}

IRenderTexture IClyde.CreateRenderTarget(Vector2i size, RenderTargetFormatParameters format,
TextureSampleParameters? sampleParameters, string? name)
{
Expand Down Expand Up @@ -204,7 +218,8 @@ private RenderTexture CreateRenderTarget(Vector2i size, RenderTargetFormatParame
Size = size,
TextureHandle = textureObject.TextureId,
MemoryPressure = pressure,
ColorFormat = format.ColorFormat
ColorFormat = format.ColorFormat,
SampleParameters = sampleParameters,
};

//GC.AddMemoryPressure(pressure);
Expand Down Expand Up @@ -251,9 +266,15 @@ private void BindRenderTargetFull(RenderTargetBase rt)
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private LoadedRenderTarget RtToLoaded(RenderTargetBase rt)
private LoadedRenderTarget RtToLoaded(IRenderTarget rt)
{
return _renderTargets[rt.Handle];
switch (rt)
{
case RenderTargetBase based:
return _renderTargets[based.Handle];
default:
throw new NotImplementedException();
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down Expand Up @@ -302,6 +323,8 @@ private sealed class LoadedRenderTarget
// Renderbuffer handle
public GLHandle DepthStencilHandle;
public long MemoryPressure;

public TextureSampleParameters? SampleParameters;
}

private abstract class RenderTargetBase : IRenderTarget
Expand Down
23 changes: 17 additions & 6 deletions Robust.Client/Graphics/Clyde/Clyde.Rendering.cs
Original file line number Diff line number Diff line change
Expand Up @@ -859,15 +859,17 @@ private void BreakBatch()

private FullStoredRendererState PushRenderStateFull()
{
return new FullStoredRendererState(_currentMatrixProj, _currentMatrixView, _currentRenderTarget);
return new FullStoredRendererState(_currentMatrixProj, _currentMatrixView, _currentBoundRenderTarget, _currentRenderTarget, _queuedShaderInstance);
}

private void PopRenderStateFull(in FullStoredRendererState state)
{
SetProjViewFull(state.ProjMatrix, state.ViewMatrix);
BindRenderTargetFull(state.RenderTarget);
BindRenderTargetImmediate(state.BoundRenderTarget);

var (width, height) = state.RenderTarget.Size;
_queuedShaderInstance = state.QueuedShaderInstance;
_currentRenderTarget = state.RenderTarget;
var (width, height) = state.BoundRenderTarget.Size;
GL.Viewport(0, 0, width, height);
CheckGlError();
}
Expand Down Expand Up @@ -1061,14 +1063,23 @@ private readonly struct FullStoredRendererState
{
public readonly Matrix3x2 ProjMatrix;
public readonly Matrix3x2 ViewMatrix;
public readonly LoadedRenderTarget BoundRenderTarget;
public readonly LoadedRenderTarget RenderTarget;

public FullStoredRendererState(in Matrix3x2 projMatrix, in Matrix3x2 viewMatrix,
LoadedRenderTarget renderTarget)
public readonly ClydeShaderInstance QueuedShaderInstance;

public FullStoredRendererState(
in Matrix3x2 projMatrix,
in Matrix3x2 viewMatrix,
LoadedRenderTarget boundRenderTarget,
LoadedRenderTarget renderTarget,
ClydeShaderInstance queuedShaderInstance
)
{
ProjMatrix = projMatrix;
ViewMatrix = viewMatrix;
BoundRenderTarget = boundRenderTarget;
RenderTarget = renderTarget;
QueuedShaderInstance = queuedShaderInstance;
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions Robust.Client/Graphics/Clyde/Clyde.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Profiling;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using TextureWrapMode = Robust.Shared.Graphics.TextureWrapMode;

Expand All @@ -36,6 +37,7 @@ internal sealed partial class Clyde : IClydeInternal, IPostInjectInit, IEntityEv
[Dependency] private readonly ILogManager _logManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IOverlayManager _overlayManager = default!;
[Dependency] private readonly IPrototypeManager _protoMan = default!;
[Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IResourceManager _resManager = default!;
[Dependency] private readonly IUserInterfaceManagerInternal _userInterfaceManager = default!;
Expand Down
5 changes: 5 additions & 0 deletions Robust.Client/Graphics/Clyde/ClydeHeadless.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ public OwnedTexture CreateBlankTexture<T>(
return new DummyTexture(size);
}

public IRenderTexture CreateLightRenderTarget(Vector2i size, string? name = null, bool depthStencil = true)
{
return CreateRenderTarget(size, new RenderTargetFormatParameters(RenderTargetColorFormat.R8, hasDepthStencil: depthStencil), null, name: name);
}

public IRenderTexture CreateRenderTarget(Vector2i size, RenderTargetFormatParameters format,
TextureSampleParameters? sampleParameters = null, string? name = null)
{
Expand Down
2 changes: 2 additions & 0 deletions Robust.Client/Graphics/IClyde.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ OwnedTexture CreateBlankTexture<T>(
in TextureLoadParameters? loadParams = null)
where T : unmanaged, IPixel<T>;

IRenderTexture CreateLightRenderTarget(Vector2i size, string? name = null, bool depthStencil = true);

IRenderTexture CreateRenderTarget(Vector2i size, RenderTargetFormatParameters format,
TextureSampleParameters? sampleParameters = null, string? name = null);

Expand Down
Loading
Loading