Skip to content

Commit

Permalink
pass stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
metalgearsloth committed Sep 29, 2024
1 parent bc117ca commit 5343598
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,6 @@ private void OnLightingPass(ref LightingPassEvent ev)

private sealed class LightComparer : IComparer<RenderLight>
{
public int MaxLights;
public Vector2 WorldPos;

public int Compare(RenderLight x, RenderLight y)
{
if (x.CastShadows != y.CastShadows)
Expand Down
152 changes: 96 additions & 56 deletions Robust.Client/Graphics/Clyde/Clyde.LightRendering.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using TKStencilOp = OpenToolkit.Graphics.OpenGL4.StencilOp;
using Robust.Shared.Physics;
using Robust.Client.ComponentTrees;
using Robust.Shared.Enums;
using Robust.Shared.Graphics;
using static Robust.Shared.GameObjects.OccluderComponent;
using Robust.Shared.Utility;
Expand Down Expand Up @@ -95,8 +96,7 @@ internal partial class Clyde
private ClydeTexture FovTexture => _fovRenderTarget.Texture;
private ClydeTexture ShadowTexture => _shadowRenderTarget.Texture;

private LightCapacityComparer _lightCap = new();
private ShadowCapacityComparer _shadowCap = new ShadowCapacityComparer();
private readonly Dictionary<string, IRenderTexture> _namedRenderTargets = new();

private unsafe void InitLighting()
{
Expand Down Expand Up @@ -252,7 +252,6 @@ private void DrawFov(Viewport viewport, IEye eye)
/// <param name="width">The width of the current framebuffer.</param>
/// <param name="maxDist">The maximum distance of this light.</param>
/// <param name="viewportY">Y index of the row to render the depth at in the framebuffer.</param>
/// </param>
private void DrawOcclusionDepth(Vector2 lightPos, int width, float maxDist, int viewportY)
{
// The light is now the center of the universe.
Expand Down Expand Up @@ -355,6 +354,7 @@ private void DrawLightsAndFov(Viewport viewport, Box2Rotated worldBounds, Box2 w
Map = (mapUid, _entityManager.GetComponent<MapComponent>(mapUid)),
WorldBounds = worldBounds,
WorldAabb = worldAABB,
WorldHandle = _renderHandle.DrawingHandleWorld,
};

// Collect content details
Expand Down Expand Up @@ -393,46 +393,43 @@ private void DrawLightsAndFov(Viewport viewport, Box2Rotated worldBounds, Box2 w
pass.WorldBounds = worldBounds;
pass.WorldAabb = worldAABB;
pass.Scale = pass.Scale == Vector2.Zero ? viewport.RenderScale : Vector2.One;
RenderLightingPass(viewport, pass, eye);
RenderLightingPass(viewport, ref passEv, ref pass, eye);
}

foreach (var pass in passEv.Passes)
{
if (!pass.Bind)
continue;

BindRenderTargetFull(viewport.RenderTarget);
GL.Viewport(0, 0, viewport.Size.X, viewport.Size.Y);
CheckGlError();
}
BindRenderTargetFull(viewport.RenderTarget);
GL.Viewport(0, 0, viewport.Size.X, viewport.Size.Y);
CheckGlError();

_lightingReady = true;
}

private void RenderLightingPass(Viewport viewport, LightingPass pass, IEye eye)
private void RenderLightingPass(Viewport viewport, ref LightingPassEvent ev, ref LightingPass pass, IEye eye)
{
using (DebugGroup("Draw shadow depth"))
using (_prof.Group("Draw shadow depth"))
if (pass.Lights.Count > 0)
{
PrepareDepthDraw(RtToLoaded(_shadowRenderTarget));
GL.CullFace(CullFaceMode.Back);
CheckGlError();

if (pass.DrawShadows)
using (DebugGroup("Draw shadow depth"))
using (_prof.Group("Draw shadow depth"))
{
for (var i = 0; i < pass.Lights.Count; i++)
PrepareDepthDraw(RtToLoaded(_shadowRenderTarget));
GL.CullFace(CullFaceMode.Back);
CheckGlError();

if (pass.DrawShadows)
{
var light = pass.Lights[i];
for (var i = 0; i < pass.Lights.Count; i++)
{
var light = pass.Lights[i];

if (!light.CastShadows) continue;
if (!light.CastShadows) continue;

DrawOcclusionDepth(light.Position, ShadowMapSize, light.Radius, i);
DrawOcclusionDepth(light.Position, ShadowMapSize, light.Radius, i);
}
}
}

FinalizeDepthDraw();
}

FinalizeDepthDraw();

GL.Enable(EnableCap.StencilTest);
_isStencilling = true;

Expand Down Expand Up @@ -555,24 +552,33 @@ private void RenderLightingPass(Viewport viewport, LightingPass pass, IEye eye)

_drawQuad(-offset, offset, matrix, lightShader);
}

// Any custom lighting to be applied.
pass.InvokeAfterLight(ev);
}

ResetBlendFunc();
GL.Disable(EnableCap.StencilTest);
_isStencilling = false;
CheckGlError();

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

using (_prof.Group("BlurOntoWalls"))
if (pass.Target is RenderTexture realTarget)
{
BlurOntoWalls(viewport, eye);
}
if (_cfg.GetCVar(CVars.LightBlur))
BlurLights(viewport, realTarget, eye);

using (_prof.Group("MergeWallLayer"))
{
MergeWallLayer(viewport);
using (_prof.Group("BlurOntoWalls"))
{
BlurOntoWalls(viewport, realTarget, eye);
}

if (pass.MergeWallLayer)
{
using (_prof.Group("MergeWallLayer"))
{
MergeWallLayer(viewport, realTarget);
}
}
}
}

Expand All @@ -598,7 +604,7 @@ public int Compare(
}
}

private void BlurLights(Viewport viewport, IEye eye)
private void BlurLights(Viewport viewport, IRenderTexture target, IEye eye)
{
using var _ = DebugGroup(nameof(BlurLights));

Expand All @@ -610,9 +616,12 @@ private void BlurLights(Viewport viewport, IEye eye)
var shader = _loadedShaders[_lightBlurShaderHandle].Program;
shader.Use();

SetupGlobalUniformsImmediate(shader, viewport.LightRenderTarget.Texture);
if (target is RenderTexture realTarget)
{
SetupGlobalUniformsImmediate(shader, realTarget.Texture);
}

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

Expand All @@ -622,7 +631,7 @@ 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, target.Texture);

// Have to scale the blurring radius based on viewport size and camera zoom.
const float refCameraHeight = 14;
Expand Down Expand Up @@ -661,7 +670,7 @@ private void BlurLights(Viewport viewport, IEye eye)
SetProjViewBuffer(_currentMatrixProj, _currentMatrixView);
}

private void BlurOntoWalls(Viewport viewport, IEye eye)
private void BlurOntoWalls(Viewport viewport, IRenderTexture target, IEye eye)
{
using var _ = DebugGroup(nameof(BlurOntoWalls));

Expand All @@ -673,7 +682,10 @@ private void BlurOntoWalls(Viewport viewport, IEye eye)
var shader = _loadedShaders[_wallBleedBlurShaderHandle].Program;
shader.Use();

SetupGlobalUniformsImmediate(shader, viewport.LightRenderTarget.Texture);
if (target is RenderTexture realTarget)
{
SetupGlobalUniformsImmediate(shader, realTarget.Texture);
}

shader.SetUniformMaybe("size", (Vector2)viewport.WallBleedIntermediateRenderTarget1.Size);
shader.SetUniformTextureMaybe(UniIMainTexture, TextureUnit.Texture0);
Expand All @@ -685,7 +697,7 @@ private void BlurOntoWalls(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, target.Texture);

// Have to scale the blurring radius based on viewport size and camera zoom.
const float refCameraHeight = 14;
Expand Down Expand Up @@ -722,13 +734,13 @@ private void BlurOntoWalls(Viewport viewport, IEye eye)
SetProjViewBuffer(_currentMatrixProj, _currentMatrixView);
}

private void MergeWallLayer(Viewport viewport)
private void MergeWallLayer(Viewport viewport, RenderTexture target)
{
using var _ = DebugGroup(nameof(MergeWallLayer));

BindRenderTargetFull(viewport.LightRenderTarget);
BindRenderTargetFull(target);

GL.Viewport(0, 0, viewport.LightRenderTarget.Size.X, viewport.LightRenderTarget.Size.Y);
GL.Viewport(0, 0, target.Size.X, target.Size.Y);
CheckGlError();
GL.Disable(EnableCap.Blend);
CheckGlError();
Expand Down Expand Up @@ -1125,15 +1137,28 @@ private void RegenLightRts(Viewport viewport)

public IRenderTexture CreateLightRenderTarget(IClydeViewport viewport, string name)
{
// Re-use existing one if it exists.
if (_namedRenderTargets.TryGetValue(name, out var texture))
{
if (texture.Size == viewport.Size)
return texture;

texture.Dispose();
}

var lightMapColorFormat = _hasGLFloatFramebuffers
? RenderTargetColorFormat.R11FG11FB10F
: RenderTargetColorFormat.Rgba8;

var shrimps = new TextureSampleParameters { Filter = true };
return CreateRenderTarget(GetLightMapSize(viewport.Size),
texture = CreateRenderTarget(GetLightMapSize(viewport.Size),
new RenderTargetFormatParameters(lightMapColorFormat, hasDepthStencil: true),
shrimps,
name);

_namedRenderTargets[name] = texture;

return texture;
}

private void RegenAllLightRts()
Expand Down Expand Up @@ -1235,18 +1260,21 @@ public record struct RenderLight()
public float Softness { get; set; } = 1f;
}

public record struct LightingPass()
public sealed class LightingPass()
{
/// <summary>
/// Will this pass get bound to the viewport.
/// Will this pass get bound to the viewport? Defaults to false so can be used independently in its own framebuffer.
/// </summary>
internal bool Bind = false;
public bool Bind = false;

private IClydeViewport Viewport;
private IClydeViewport Viewport = default!;

public Vector2 Scale { get; set; } = Vector2.Zero;

public IRenderTarget Target;

public bool MergeWallLayer = true;

public IRenderTarget Target = default!;

public bool DrawShadows = true;

Expand All @@ -1257,22 +1285,34 @@ public record struct LightingPass()

public Color ClearColor = Color.Transparent;

/// <summary>
/// Event to be invoked after rendering lights.
/// </summary>
public event Action<LightingPassEvent, LightingPass>? AfterLightRender;

internal void InvokeAfterLight(LightingPassEvent ev)
{
AfterLightRender?.Invoke(ev, this);
}

public void SetClearColor(Color? color)
{
ClearColor = color ?? Color.Transparent;
}
}

[ByRefEvent]
public record struct LightingPassEvent()
public sealed class LightingPassEvent()
{
/*
* Viewport data
*/
* Viewport data
*/
public MapId MapId => Map.Comp.MapId;
public Entity<MapComponent> Map;

public IClydeViewport Viewport;
public DrawingHandleWorld WorldHandle = default!;

public IClydeViewport Viewport = default!;

public Box2Rotated WorldBounds;

Expand Down

0 comments on commit 5343598

Please sign in to comment.