mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-15 14:52:35 +02:00
Moving a ton of rendering code around and it somehow still works somewhat.
This commit is contained in:
@@ -26,7 +26,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
}
|
||||
|
||||
SetTexture(TextureUnit.Texture0, _tileDefinitionManager.TileTextureAtlas);
|
||||
SetTexture(TextureUnit.Texture1, _lightingReady ? _lightRenderTarget.Texture : _stockTextureWhite);
|
||||
SetTexture(TextureUnit.Texture1, _lightingReady ? _currentViewport!.LightRenderTarget.Texture : _stockTextureWhite);
|
||||
|
||||
var (gridProgram, _) = ActivateShaderInstance(_defaultShader.Handle);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.GameObjects.EntitySystems;
|
||||
@@ -60,62 +60,24 @@ namespace Robust.Client.Graphics.Clyde
|
||||
return;
|
||||
}
|
||||
|
||||
void RenderOverlays(OverlaySpace space)
|
||||
{
|
||||
using (DebugGroup($"Overlays: {space}"))
|
||||
{
|
||||
foreach (var overlay in _overlayManager.AllOverlays
|
||||
.Where(o => o.Space == space)
|
||||
.OrderBy(o => o.ZIndex))
|
||||
{
|
||||
overlay.ClydeRender(_renderHandle);
|
||||
}
|
||||
|
||||
FlushRenderQueue();
|
||||
}
|
||||
}
|
||||
|
||||
RenderOverlays(OverlaySpace.ScreenSpaceBelowWorld);
|
||||
|
||||
SetSpaceFull(CurrentSpace.WorldSpace);
|
||||
|
||||
// Calculate world-space AABB for camera, to cull off-screen things.
|
||||
var eye = _eyeManager.CurrentEye;
|
||||
var worldBounds = Box2.CenteredAround(eye.Position.Position,
|
||||
_framebufferSize / (float) EyeManager.PixelsPerMeter * eye.Zoom);
|
||||
|
||||
if (_eyeManager.CurrentMap != MapId.Nullspace)
|
||||
{
|
||||
using (DebugGroup("Lights"))
|
||||
{
|
||||
DrawLightsAndFov(worldBounds, eye);
|
||||
}
|
||||
|
||||
using (DebugGroup("Grids"))
|
||||
{
|
||||
_drawGrids(worldBounds);
|
||||
}
|
||||
|
||||
using (DebugGroup("Entities"))
|
||||
{
|
||||
DrawEntities(worldBounds);
|
||||
}
|
||||
|
||||
RenderOverlays(OverlaySpace.WorldSpace);
|
||||
|
||||
if (_lightManager.Enabled && eye.DrawFov)
|
||||
{
|
||||
ApplyFovToBuffer(eye);
|
||||
}
|
||||
}
|
||||
|
||||
_lightingReady = false;
|
||||
RenderViewport(_mainViewport);
|
||||
|
||||
SetSpaceFull(CurrentSpace.ScreenSpace);
|
||||
|
||||
// TODO: Re-enable this
|
||||
/*
|
||||
if (DebugLayers == ClydeDebugLayers.Fov)
|
||||
{
|
||||
// I'm refactoring this code and I found this comment:
|
||||
// NOTE
|
||||
// Yes, it just says "NOTE". Thank you past me.
|
||||
// Anyways I'm 99% sure this was about the fact that this debug layer is actually broken.
|
||||
// Because the math is wrong.
|
||||
// So there are distortions from incorrect projection.
|
||||
_renderHandle.UseShader(_fovDebugShaderInstance);
|
||||
_renderHandle.DrawingHandleScreen.SetTransform(Matrix3.Identity);
|
||||
var pos = UIBox2.FromDimensions(ScreenSize / 2 - (200, 200), (400, 400));
|
||||
@@ -128,6 +90,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
_renderHandle.DrawingHandleScreen.SetTransform(Matrix3.Identity);
|
||||
_renderHandle.DrawingHandleScreen.DrawTextureRect(_wallBleedIntermediateRenderTarget2.Texture, UIBox2.FromDimensions(Vector2.Zero, ScreenSize), new Color(1, 1, 1, 0.5f));
|
||||
}
|
||||
*/
|
||||
|
||||
TakeScreenshot(ScreenshotType.BeforeUI);
|
||||
|
||||
@@ -145,13 +108,40 @@ namespace Robust.Client.Graphics.Clyde
|
||||
SwapBuffers();
|
||||
}
|
||||
|
||||
private void DrawEntities(Box2 worldBounds)
|
||||
private void RenderOverlays(OverlaySpace space)
|
||||
{
|
||||
using (DebugGroup($"Overlays: {space}"))
|
||||
{
|
||||
var list = new List<Overlay>();
|
||||
|
||||
foreach (var overlay in _overlayManager.AllOverlays)
|
||||
{
|
||||
if (overlay.Space == space)
|
||||
{
|
||||
list.Add(overlay);
|
||||
}
|
||||
}
|
||||
|
||||
list.Sort(OverlayComparer.Instance);
|
||||
|
||||
foreach (var overlay in list)
|
||||
{
|
||||
overlay.ClydeRender(_renderHandle);
|
||||
}
|
||||
|
||||
FlushRenderQueue();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEntities(Viewport viewport, Box2 worldBounds)
|
||||
{
|
||||
if (_eyeManager.CurrentMap == MapId.Nullspace || !_mapManager.HasMapEntity(_eyeManager.CurrentMap))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var screenSize = viewport.Size;
|
||||
|
||||
// So we could calculate the correct size of the entities based on the contents of their sprite...
|
||||
// Or we can just assume that no entity is larger than 10x10 and get a stupid easy check.
|
||||
// TODO: Make this check more accurate.
|
||||
@@ -183,9 +173,9 @@ namespace Robust.Client.Graphics.Clyde
|
||||
var spritePos = entry.sprite.Owner.Transform.WorldPosition;
|
||||
var screenPos = _eyeManager.WorldToScreen(spritePos);
|
||||
var (roundedX, roundedY) = roundedPos = (Vector2i) screenPos;
|
||||
var flippedPos = new Vector2i(roundedX, ScreenSize.Y - roundedY);
|
||||
var flippedPos = new Vector2i(roundedX, screenSize.Y - roundedY);
|
||||
flippedPos -= EntityPostRenderTarget.Size / 2;
|
||||
_renderHandle.Viewport(Box2i.FromDimensions(-flippedPos, ScreenSize));
|
||||
_renderHandle.Viewport(Box2i.FromDimensions(-flippedPos, screenSize));
|
||||
}
|
||||
|
||||
entry.sprite.Render(_renderHandle.DrawingHandleWorld, entry.worldMatrix, entry.worldRotation);
|
||||
@@ -193,7 +183,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
if (entry.sprite.PostShader != null)
|
||||
{
|
||||
_renderHandle.UseRenderTarget(null);
|
||||
_renderHandle.Viewport(Box2i.FromDimensions(Vector2i.Zero, ScreenSize));
|
||||
_renderHandle.Viewport(Box2i.FromDimensions(Vector2i.Zero, screenSize));
|
||||
|
||||
_renderHandle.UseShader(entry.sprite.PostShader);
|
||||
_renderHandle.SetSpace(CurrentSpace.ScreenSpace);
|
||||
@@ -251,5 +241,57 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
handle.DrawingHandleScreen.DrawTexture(texture, (ScreenSize - texture.Size) / 2);
|
||||
}
|
||||
|
||||
private void RenderViewport(Viewport viewport)
|
||||
{
|
||||
var oldVp = _currentViewport;
|
||||
_currentViewport = viewport;
|
||||
|
||||
// Calculate world-space AABB for camera, to cull off-screen things.
|
||||
var eye = _eyeManager.CurrentEye;
|
||||
var worldBounds = Box2.CenteredAround(eye.Position.Position,
|
||||
_framebufferSize / (float) EyeManager.PixelsPerMeter * eye.Zoom);
|
||||
|
||||
if (_eyeManager.CurrentMap != MapId.Nullspace)
|
||||
{
|
||||
using (DebugGroup("Lights"))
|
||||
{
|
||||
DrawLightsAndFov(viewport, worldBounds, eye);
|
||||
}
|
||||
|
||||
using (DebugGroup("Grids"))
|
||||
{
|
||||
_drawGrids(worldBounds);
|
||||
}
|
||||
|
||||
using (DebugGroup("Entities"))
|
||||
{
|
||||
DrawEntities(viewport, worldBounds);
|
||||
}
|
||||
|
||||
RenderOverlays(OverlaySpace.WorldSpace);
|
||||
|
||||
if (_lightManager.Enabled && eye.DrawFov)
|
||||
{
|
||||
ApplyFovToBuffer(viewport, eye);
|
||||
}
|
||||
}
|
||||
|
||||
_lightingReady = false;
|
||||
|
||||
_currentViewport = oldVp;
|
||||
}
|
||||
|
||||
private sealed class OverlayComparer : IComparer<Overlay>
|
||||
{
|
||||
public static readonly OverlayComparer Instance = new OverlayComparer();
|
||||
|
||||
public int Compare(Overlay x, Overlay y)
|
||||
{
|
||||
var zX = x.ZIndex ?? 0;
|
||||
var zY = y.ZIndex ?? 0;
|
||||
return zX.CompareTo(zY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,30 +46,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
// We keep this around so we can reverse the effects while overlaying actual FOV.
|
||||
private Matrix4 _fovProjection;
|
||||
|
||||
// Various render targets used in the light rendering process.
|
||||
|
||||
// Lighting is drawn into this. This then gets sampled later while rendering world-space stuff.
|
||||
private RenderTarget _lightRenderTarget = default!;
|
||||
|
||||
// For depth calculation for FOV.
|
||||
private RenderTarget _fovRenderTarget = default!;
|
||||
|
||||
// For depth calculation of lighting shadows.
|
||||
private RenderTarget _shadowRenderTarget = default!;
|
||||
|
||||
// Unused, to be removed.
|
||||
private RenderTarget _wallMaskRenderTarget = default!;
|
||||
|
||||
// Two render targets used to apply gaussian blur to the _lightRenderTarget so it bleeds "into" walls.
|
||||
// We need two of them because efficient blur works in two stages and also we're doing multiple iterations.
|
||||
private RenderTarget _wallBleedIntermediateRenderTarget1 = default!;
|
||||
private RenderTarget _wallBleedIntermediateRenderTarget2 = default!;
|
||||
|
||||
// Proxies to textures of some of the above render targets.
|
||||
private ClydeTexture FovTexture => _fovRenderTarget.Texture;
|
||||
|
||||
private ClydeTexture ShadowTexture => _shadowRenderTarget.Texture;
|
||||
|
||||
// Sampler used to sample the FovTexture with linear filtering, used in the lighting FOV pass
|
||||
// (it uses VSM unlike final FOV).
|
||||
private GLHandle _fovFilterSampler;
|
||||
@@ -100,12 +76,21 @@ namespace Robust.Client.Graphics.Clyde
|
||||
private GLBuffer _occlusionMaskEbo = default!;
|
||||
private GLHandle _occlusionMaskVao;
|
||||
|
||||
// For depth calculation for FOV.
|
||||
private RenderTarget _fovRenderTarget = default!;
|
||||
|
||||
// For depth calculation of lighting shadows.
|
||||
private RenderTarget _shadowRenderTarget = default!;
|
||||
|
||||
// Proxies to textures of the above render targets.
|
||||
private ClydeTexture FovTexture => _fovRenderTarget.Texture;
|
||||
private ClydeTexture ShadowTexture => _shadowRenderTarget.Texture;
|
||||
|
||||
|
||||
private unsafe void InitLighting()
|
||||
{
|
||||
LoadLightingShaders();
|
||||
|
||||
RegenerateLightingRenderTargets();
|
||||
|
||||
{
|
||||
// Occlusion VAO.
|
||||
// Only handles positions, no other vertex data necessary.
|
||||
@@ -194,7 +179,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
_mergeWallLayerShaderHandle = LoadShaderHandle("/Shaders/Internal/wall-merge.swsl");
|
||||
}
|
||||
|
||||
private void DrawFov(IEye eye)
|
||||
private void DrawFov(Viewport viewport, IEye eye)
|
||||
{
|
||||
using var _ = DebugGroup(nameof(DrawFov));
|
||||
|
||||
@@ -203,7 +188,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
if (eye.DrawFov)
|
||||
{
|
||||
// Calculate maximum distance for the projection based on screen size.
|
||||
var screenSizeCut = ScreenSize / EyeManager.PixelsPerMeter;
|
||||
var screenSizeCut = viewport.Size / EyeManager.PixelsPerMeter;
|
||||
var maxDist = (float) Math.Max(screenSizeCut.X, screenSizeCut.Y);
|
||||
|
||||
// FOV is rendered twice.
|
||||
@@ -312,7 +297,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
GL.Disable(EnableCap.CullFace);
|
||||
}
|
||||
|
||||
private void DrawLightsAndFov(Box2 worldBounds, IEye eye)
|
||||
private void DrawLightsAndFov(Viewport viewport, Box2 worldBounds, IEye eye)
|
||||
{
|
||||
if (!_lightManager.Enabled)
|
||||
{
|
||||
@@ -325,7 +310,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
UpdateOcclusionGeometry(map, expandedBounds, eye.Position.Position);
|
||||
|
||||
DrawFov(eye);
|
||||
DrawFov(viewport, eye);
|
||||
|
||||
var shadowMatrices = new Matrix4[lights.Count];
|
||||
|
||||
@@ -347,11 +332,11 @@ namespace Robust.Client.Graphics.Clyde
|
||||
FinalizeDepthDraw();
|
||||
}
|
||||
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, _lightRenderTarget.ObjectHandle.Handle);
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, viewport.LightRenderTarget.ObjectHandle.Handle);
|
||||
GLClearColor(Color.FromSrgb(AmbientLightColor));
|
||||
GL.Clear(ClearBufferMask.ColorBufferBit);
|
||||
|
||||
var (lightW, lightH) = GetLightMapSize();
|
||||
var (lightW, lightH) = GetLightMapSize(viewport.Size);
|
||||
GL.Viewport(0, 0, lightW, lightH);
|
||||
|
||||
var lightShader = _loadedShaders[_lightShaderHandle].Program;
|
||||
@@ -442,14 +427,14 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
||||
|
||||
ApplyLightingFovToBuffer(eye);
|
||||
ApplyLightingFovToBuffer(viewport, eye);
|
||||
|
||||
BlurOntoWalls(eye);
|
||||
BlurOntoWalls(viewport, eye);
|
||||
|
||||
MergeWallLayer();
|
||||
MergeWallLayer(viewport);
|
||||
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
|
||||
GL.Viewport(0, 0, ScreenSize.X, ScreenSize.Y);
|
||||
GL.Viewport(0, 0, viewport.Size.X, viewport.Size.Y);
|
||||
|
||||
_lightingReady = true;
|
||||
}
|
||||
@@ -493,7 +478,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
return (lights, expandedBounds);
|
||||
}
|
||||
|
||||
private void BlurOntoWalls(IEye eye)
|
||||
private void BlurOntoWalls(Viewport viewport, IEye eye)
|
||||
{
|
||||
using var _ = DebugGroup(nameof(BlurOntoWalls));
|
||||
|
||||
@@ -503,20 +488,20 @@ namespace Robust.Client.Graphics.Clyde
|
||||
var shader = _loadedShaders[_wallBleedBlurShaderHandle].Program;
|
||||
shader.Use();
|
||||
|
||||
shader.SetUniformMaybe("size", (Vector2) _wallBleedIntermediateRenderTarget1.Size);
|
||||
shader.SetUniformMaybe("size", (Vector2) viewport.WallBleedIntermediateRenderTarget1.Size);
|
||||
shader.SetUniformTextureMaybe(UniIMainTexture, TextureUnit.Texture0);
|
||||
|
||||
var size = _wallBleedIntermediateRenderTarget1.Size;
|
||||
var size = viewport.WallBleedIntermediateRenderTarget1.Size;
|
||||
GL.Viewport(0, 0, size.X, size.Y);
|
||||
|
||||
// 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, _lightRenderTarget.Texture);
|
||||
SetTexture(TextureUnit.Texture0, viewport.LightRenderTarget.Texture);
|
||||
|
||||
// Have to scale the blurring radius based on viewport size and camera zoom.
|
||||
const float refCameraHeight = 14;
|
||||
var cameraSize = eye.Zoom.Y * ScreenSize.Y / EyeManager.PixelsPerMeter;
|
||||
var cameraSize = eye.Zoom.Y * viewport.Size.Y / EyeManager.PixelsPerMeter;
|
||||
// 7e-3f is just a magic factor that makes it look ok.
|
||||
var factor = 7e-3f * (refCameraHeight / cameraSize);
|
||||
|
||||
@@ -527,39 +512,39 @@ namespace Robust.Client.Graphics.Clyde
|
||||
// Set factor.
|
||||
shader.SetUniformMaybe("radius", scale);
|
||||
|
||||
_wallBleedIntermediateRenderTarget1.Bind();
|
||||
viewport.WallBleedIntermediateRenderTarget1.Bind();
|
||||
|
||||
// Blur horizontally to _wallBleedIntermediateRenderTarget1.
|
||||
shader.SetUniformMaybe("direction", Vector2.UnitX);
|
||||
_drawQuad(Vector2.Zero, ScreenSize, Matrix3.Identity, shader);
|
||||
_drawQuad(Vector2.Zero, viewport.Size, Matrix3.Identity, shader);
|
||||
|
||||
SetTexture(TextureUnit.Texture0, _wallBleedIntermediateRenderTarget1.Texture);
|
||||
_wallBleedIntermediateRenderTarget2.Bind();
|
||||
SetTexture(TextureUnit.Texture0, viewport.WallBleedIntermediateRenderTarget1.Texture);
|
||||
viewport.WallBleedIntermediateRenderTarget2.Bind();
|
||||
|
||||
// Blur vertically to _wallBleedIntermediateRenderTarget2.
|
||||
shader.SetUniformMaybe("direction", Vector2.UnitY);
|
||||
_drawQuad(Vector2.Zero, ScreenSize, Matrix3.Identity, shader);
|
||||
_drawQuad(Vector2.Zero, viewport.Size, Matrix3.Identity, shader);
|
||||
|
||||
SetTexture(TextureUnit.Texture0, _wallBleedIntermediateRenderTarget2.Texture);
|
||||
SetTexture(TextureUnit.Texture0, viewport.WallBleedIntermediateRenderTarget2.Texture);
|
||||
}
|
||||
|
||||
GL.Enable(EnableCap.Blend);
|
||||
_setSpace(CurrentSpace.WorldSpace);
|
||||
}
|
||||
|
||||
private void MergeWallLayer()
|
||||
private void MergeWallLayer(Viewport viewport)
|
||||
{
|
||||
using var _ = DebugGroup(nameof(MergeWallLayer));
|
||||
|
||||
_lightRenderTarget.Bind();
|
||||
viewport.LightRenderTarget.Bind();
|
||||
|
||||
GL.Viewport(0, 0, _lightRenderTarget.Size.X, _lightRenderTarget.Size.Y);
|
||||
GL.Viewport(0, 0, viewport.LightRenderTarget.Size.X, viewport.LightRenderTarget.Size.Y);
|
||||
GL.Disable(EnableCap.Blend);
|
||||
|
||||
var shader = _loadedShaders[_mergeWallLayerShaderHandle].Program;
|
||||
shader.Use();
|
||||
|
||||
var tex = _wallBleedIntermediateRenderTarget2.Texture;
|
||||
var tex = viewport.WallBleedIntermediateRenderTarget2.Texture;
|
||||
SetTexture(TextureUnit.Texture0, tex);
|
||||
|
||||
shader.SetUniformTextureMaybe(UniIMainTexture, TextureUnit.Texture0);
|
||||
@@ -572,7 +557,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
GL.Enable(EnableCap.Blend);
|
||||
}
|
||||
|
||||
private void ApplyFovToBuffer(IEye eye)
|
||||
private void ApplyFovToBuffer(Viewport viewport, IEye eye)
|
||||
{
|
||||
// Applies FOV to the final framebuffer.
|
||||
|
||||
@@ -585,10 +570,10 @@ namespace Robust.Client.Graphics.Clyde
|
||||
fovShader.SetUniformMaybe("shadowMatrix", _fovProjection, false);
|
||||
fovShader.SetUniformMaybe("center", eye.Position.Position);
|
||||
|
||||
DrawBlit(fovShader);
|
||||
DrawBlit(viewport.Size, fovShader);
|
||||
}
|
||||
|
||||
private void ApplyLightingFovToBuffer(IEye eye)
|
||||
private void ApplyLightingFovToBuffer(Viewport viewport, IEye eye)
|
||||
{
|
||||
// Applies FOV to the lighting framebuffer.
|
||||
|
||||
@@ -605,15 +590,15 @@ namespace Robust.Client.Graphics.Clyde
|
||||
fovShader.SetUniformMaybe("shadowMatrix", _fovProjection, false);
|
||||
fovShader.SetUniformMaybe("center", eye.Position.Position);
|
||||
|
||||
DrawBlit(fovShader);
|
||||
DrawBlit(viewport.Size, fovShader);
|
||||
|
||||
GL.BindSampler(0, 0);
|
||||
}
|
||||
|
||||
private void DrawBlit(GLShaderProgram shader)
|
||||
private void DrawBlit(Vector2i screenSize, GLShaderProgram shader)
|
||||
{
|
||||
_drawQuad(_eyeManager.ScreenToMap((-1, -1)).Position,
|
||||
_eyeManager.ScreenToMap(ScreenSize + Vector2i.One).Position,
|
||||
_eyeManager.ScreenToMap(screenSize + Vector2i.One).Position,
|
||||
Matrix3.Identity, shader);
|
||||
}
|
||||
|
||||
@@ -811,46 +796,54 @@ namespace Robust.Client.Graphics.Clyde
|
||||
}
|
||||
}
|
||||
|
||||
private void RegenerateLightingRenderTargets()
|
||||
private void RegenLightRts(Viewport viewport)
|
||||
{
|
||||
// All of these depend on screen size so they have to be re-created if it changes.
|
||||
|
||||
var lightMapSize = GetLightMapSize();
|
||||
var lightMapSizeQuart = GetLightMapSize(true);
|
||||
var lightMapSize = GetLightMapSize(viewport.Size);
|
||||
var lightMapSizeQuart = GetLightMapSize(viewport.Size, true);
|
||||
const RenderTargetColorFormat lightMapColorFormat = RenderTargetColorFormat.R11FG11FB10F;
|
||||
var lightMapSampleParameters = new TextureSampleParameters {Filter = true};
|
||||
|
||||
_lightRenderTarget?.Delete();
|
||||
_wallMaskRenderTarget?.Delete();
|
||||
_wallBleedIntermediateRenderTarget1?.Delete();
|
||||
_wallBleedIntermediateRenderTarget2?.Delete();
|
||||
viewport.LightRenderTarget?.Delete();
|
||||
viewport.WallMaskRenderTarget?.Delete();
|
||||
viewport.WallBleedIntermediateRenderTarget1?.Delete();
|
||||
viewport.WallBleedIntermediateRenderTarget2?.Delete();
|
||||
|
||||
_wallMaskRenderTarget = CreateRenderTarget(ScreenSize, RenderTargetColorFormat.R8,
|
||||
name: nameof(_wallMaskRenderTarget));
|
||||
viewport.WallMaskRenderTarget = CreateRenderTarget(viewport.Size, RenderTargetColorFormat.R8,
|
||||
name: $"{viewport.Name}-{nameof(viewport.WallMaskRenderTarget)}");
|
||||
|
||||
_lightRenderTarget = CreateRenderTarget(lightMapSize, lightMapColorFormat,
|
||||
viewport.LightRenderTarget = CreateRenderTarget(lightMapSize, lightMapColorFormat,
|
||||
lightMapSampleParameters,
|
||||
nameof(_lightRenderTarget));
|
||||
$"{viewport.Name}-{nameof(viewport.LightRenderTarget)}");
|
||||
|
||||
_wallBleedIntermediateRenderTarget1 = CreateRenderTarget(lightMapSizeQuart, lightMapColorFormat,
|
||||
viewport.WallBleedIntermediateRenderTarget1 = CreateRenderTarget(lightMapSizeQuart, lightMapColorFormat,
|
||||
lightMapSampleParameters,
|
||||
nameof(_wallBleedIntermediateRenderTarget1));
|
||||
$"{viewport.Name}-{nameof(viewport.WallBleedIntermediateRenderTarget1)}");
|
||||
|
||||
_wallBleedIntermediateRenderTarget2 = CreateRenderTarget(lightMapSizeQuart, lightMapColorFormat,
|
||||
viewport.WallBleedIntermediateRenderTarget2 = CreateRenderTarget(lightMapSizeQuart, lightMapColorFormat,
|
||||
lightMapSampleParameters,
|
||||
nameof(_wallBleedIntermediateRenderTarget2));
|
||||
$"{viewport.Name}-{nameof(viewport.WallBleedIntermediateRenderTarget2)}");
|
||||
}
|
||||
|
||||
private Vector2i GetLightMapSize(bool? overrideSetting = null)
|
||||
private void RegenAllLightRts()
|
||||
{
|
||||
foreach (var viewport in _viewports)
|
||||
{
|
||||
RegenLightRts(viewport);
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2i GetLightMapSize(Vector2i screenSize, bool? overrideSetting = null)
|
||||
{
|
||||
var setting = overrideSetting ?? _quartResLights;
|
||||
if (!setting)
|
||||
{
|
||||
return (ScreenSize.X, ScreenSize.Y);
|
||||
return screenSize;
|
||||
}
|
||||
|
||||
var w = (int) Math.Ceiling(ScreenSize.X / 2f);
|
||||
var h = (int) Math.Ceiling(ScreenSize.Y / 2f);
|
||||
var w = (int) Math.Ceiling(screenSize.X / 2f);
|
||||
var h = (int) Math.Ceiling(screenSize.Y / 2f);
|
||||
|
||||
return (w, h);
|
||||
}
|
||||
@@ -858,12 +851,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
protected override void HighResLightsChanged(bool newValue)
|
||||
{
|
||||
_quartResLights = !newValue;
|
||||
if (_lightRenderTarget == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RegenerateLightingRenderTargets();
|
||||
RegenAllLightRts();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,30 @@ namespace Robust.Client.Graphics.Clyde
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This was a dumb idea:
|
||||
|
||||
private void ResizeRenderTarget(RenderTarget rt, Vector2i newSize)
|
||||
{
|
||||
var loadedTexture = _loadedTextures[rt.Texture.TextureId];
|
||||
var textureInstance = rt.Texture;
|
||||
|
||||
// Set new sizes.
|
||||
textureInstance.SetSize(newSize);
|
||||
rt.Size = newSize;
|
||||
|
||||
// Delete old textures.
|
||||
GL.DeleteTexture(loadedTexture.OpenGLObject.Handle);
|
||||
if (rt.DepthStencilBuffer != default)
|
||||
{
|
||||
GL.DeleteRenderbuffer(rt.DepthStencilBuffer.Handle);
|
||||
}
|
||||
|
||||
// Delete the entire old framebuffer because bad OpenGL drivers will just explode otherwise.
|
||||
GL.DeleteFramebuffer(rt.ObjectHandle.Handle);
|
||||
}
|
||||
*/
|
||||
|
||||
private sealed class RenderTarget : IRenderTarget
|
||||
{
|
||||
private readonly Clyde _clyde;
|
||||
@@ -127,7 +151,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
DepthStencilBuffer = depthStencilBuffer;
|
||||
}
|
||||
|
||||
public Vector2i Size { get; }
|
||||
public Vector2i Size { get; set; }
|
||||
public ClydeTexture Texture { get; }
|
||||
public ClydeHandle Handle { get; }
|
||||
public GLHandle DepthStencilBuffer { get; }
|
||||
@@ -136,6 +160,12 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
public GLHandle ObjectHandle { get; }
|
||||
|
||||
/*
|
||||
// Used to recreate the render target on resize.
|
||||
public RenderTargetFormatParameters FormatParameters;
|
||||
public TextureSampleParameters? SampleParameters;
|
||||
*/
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
_clyde.DeleteRenderTarget(this);
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
private CurrentSpace _currentSpace;
|
||||
|
||||
private bool _lightingReady;
|
||||
private Viewport? _currentViewport;
|
||||
|
||||
/// <summary>
|
||||
/// The current model matrix we would use.
|
||||
@@ -206,7 +207,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
if (_lightingReady && loaded.HasLighting)
|
||||
{
|
||||
SetTexture(TextureUnit.Texture1, _lightRenderTarget.Texture);
|
||||
SetTexture(TextureUnit.Texture1, _currentViewport!.LightRenderTarget.Texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -8,7 +8,6 @@ using Robust.Client.Utility;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Advanced;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using OGLTextureWrapMode = OpenToolkit.Graphics.OpenGL.TextureWrapMode;
|
||||
|
||||
@@ -20,7 +19,8 @@ namespace Robust.Client.Graphics.Clyde
|
||||
private ClydeTexture _stockTextureBlack = default!;
|
||||
private ClydeTexture _stockTextureTransparent = default!;
|
||||
|
||||
private readonly Dictionary<ClydeHandle, LoadedTexture> _loadedTextures = new Dictionary<ClydeHandle, LoadedTexture>();
|
||||
private readonly Dictionary<ClydeHandle, LoadedTexture> _loadedTextures =
|
||||
new Dictionary<ClydeHandle, LoadedTexture>();
|
||||
|
||||
public Texture LoadTextureFromPNGStream(Stream stream, string? name = null,
|
||||
TextureLoadParameters? loadParams = null)
|
||||
@@ -64,6 +64,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
throw new ArgumentException("Alpha8 images must have multiple of 4 sizes.");
|
||||
}
|
||||
|
||||
internalFormat = PixelInternalFormat.R8;
|
||||
pixelDataFormat = PixelFormat.Red;
|
||||
pixelDataType = PixelType.UnsignedByte;
|
||||
@@ -160,18 +161,20 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
var (width, height) = size;
|
||||
|
||||
var id = AllocRid();
|
||||
var instance = new ClydeTexture(id, size, this);
|
||||
var loaded = new LoadedTexture
|
||||
{
|
||||
OpenGLObject = glHandle,
|
||||
Width = width,
|
||||
Height = height,
|
||||
Name = name
|
||||
Name = name,
|
||||
// TextureInstance = new WeakReference<ClydeTexture>(instance)
|
||||
};
|
||||
|
||||
var id = AllocRid();
|
||||
_loadedTextures.Add(id, loaded);
|
||||
|
||||
return new ClydeTexture(id, size, this);
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void DeleteTexture(ClydeTexture texture)
|
||||
@@ -189,16 +192,16 @@ namespace Robust.Client.Graphics.Clyde
|
||||
private void LoadStockTextures()
|
||||
{
|
||||
var white = new Image<Rgba32>(1, 1);
|
||||
white[0, 0] = new Rgba32(255,255,255,255);
|
||||
_stockTextureWhite = (ClydeTexture)Texture.LoadFromImage(white);
|
||||
white[0, 0] = new Rgba32(255, 255, 255, 255);
|
||||
_stockTextureWhite = (ClydeTexture) Texture.LoadFromImage(white);
|
||||
|
||||
var black = new Image<Rgba32>(1, 1);
|
||||
black[0, 0] = new Rgba32(0,0,0,255);
|
||||
_stockTextureBlack = (ClydeTexture)Texture.LoadFromImage(black);
|
||||
black[0, 0] = new Rgba32(0, 0, 0, 255);
|
||||
_stockTextureBlack = (ClydeTexture) Texture.LoadFromImage(black);
|
||||
|
||||
var blank = new Image<Rgba32>(1, 1);
|
||||
blank[0, 0] = new Rgba32(0,0,0,0);
|
||||
_stockTextureTransparent = (ClydeTexture)Texture.LoadFromImage(blank);
|
||||
blank[0, 0] = new Rgba32(0, 0, 0, 0);
|
||||
_stockTextureTransparent = (ClydeTexture) Texture.LoadFromImage(blank);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -240,6 +243,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
public int Height;
|
||||
public string? Name;
|
||||
public Vector2i Size => (Width, Height);
|
||||
// public WeakReference<ClydeTexture> TextureInstance;
|
||||
}
|
||||
|
||||
private sealed class ClydeTexture : OwnedTexture
|
||||
@@ -265,8 +269,14 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
return $"ClydeTexture: {loaded.Name} ({TextureId})";
|
||||
}
|
||||
|
||||
return $"ClydeTexture: ({TextureId})";
|
||||
}
|
||||
|
||||
/*public void SetSize(Vector2i newSize)
|
||||
{
|
||||
Size = newSize;
|
||||
}*/
|
||||
}
|
||||
|
||||
public Texture GetStockTexture(ClydeStockTexture stockTexture)
|
||||
@@ -281,4 +291,3 @@ namespace Robust.Client.Graphics.Clyde
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Robust.Client.Interfaces.Graphics;
|
||||
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -6,28 +7,68 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
internal sealed partial class Clyde
|
||||
{
|
||||
private Viewport CreateViewport()
|
||||
private readonly List<Viewport> _viewports = new List<Viewport>();
|
||||
|
||||
private Viewport CreateViewport(Vector2i size, string? name = null)
|
||||
{
|
||||
return new Viewport();
|
||||
var viewport = new Viewport(name);
|
||||
viewport.Size = size;
|
||||
viewport.RenderTarget = CreateRenderTarget(size,
|
||||
new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8, true),
|
||||
name: $"{name}-MainRenderTarget");
|
||||
|
||||
RegenLightRts(viewport);
|
||||
|
||||
_viewports.Add(viewport);
|
||||
|
||||
return viewport;
|
||||
}
|
||||
|
||||
IClydeViewport IClyde.CreateViewport()
|
||||
IClydeViewport IClyde.CreateViewport(Vector2i size, string? name)
|
||||
{
|
||||
return CreateViewport();
|
||||
return CreateViewport(size, name);
|
||||
}
|
||||
|
||||
private sealed class Viewport : IClydeViewport
|
||||
{
|
||||
// Primary render target.
|
||||
public RenderTarget RenderTarget = default!;
|
||||
|
||||
// Various render targets used in the light rendering process.
|
||||
|
||||
// Lighting is drawn into this. This then gets sampled later while rendering world-space stuff.
|
||||
public RenderTarget LightRenderTarget = default!;
|
||||
|
||||
// Unused, to be removed.
|
||||
public RenderTarget WallMaskRenderTarget = default!;
|
||||
|
||||
// Two render targets used to apply gaussian blur to the _lightRenderTarget so it bleeds "into" walls.
|
||||
// We need two of them because efficient blur works in two stages and also we're doing multiple iterations.
|
||||
public RenderTarget WallBleedIntermediateRenderTarget1 = default!;
|
||||
public RenderTarget WallBleedIntermediateRenderTarget2 = default!;
|
||||
|
||||
public string? Name { get; }
|
||||
|
||||
public Viewport(string? name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
|
||||
public Vector2i Size { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public IRenderTarget RenderTarget { get; }
|
||||
public IEye Eye { get; set; }
|
||||
|
||||
public void Resize(Vector2i newSize)
|
||||
IRenderTarget IClydeViewport.RenderTarget => RenderTarget;
|
||||
public IEye? Eye { get; set; }
|
||||
|
||||
/*public void Resize(Vector2i newSize)
|
||||
{
|
||||
}
|
||||
Size = newSize;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +402,8 @@ namespace Robust.Client.Graphics.Clyde
|
||||
GL.Viewport(0, 0, fbW, fbH);
|
||||
if (fbW != 0 && fbH != 0)
|
||||
{
|
||||
RegenerateLightingRenderTargets();
|
||||
_mainViewport.Dispose();
|
||||
_mainViewport = CreateViewport((fbW, fbH), nameof(_mainViewport));
|
||||
}
|
||||
|
||||
OnWindowResized?.Invoke(new WindowResizedEventArgs(oldSize, _framebufferSize));
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
private GLBuffer QuadVBO = default!;
|
||||
private GLHandle QuadVAO;
|
||||
|
||||
private Viewport _mainViewport;
|
||||
private Viewport _mainViewport = default!;
|
||||
|
||||
private bool _drawingSplash = true;
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
base.ReloadConfig();
|
||||
|
||||
RegenerateLightingRenderTargets();
|
||||
RegenAllLightRts();
|
||||
}
|
||||
|
||||
public override void PostInject()
|
||||
@@ -235,7 +235,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb, true),
|
||||
name: nameof(EntityPostRenderTarget));
|
||||
|
||||
_mainViewport = CreateViewport();
|
||||
_mainViewport = CreateViewport(_windowSize, nameof(_mainViewport));
|
||||
}
|
||||
|
||||
private void DetectOpenGLFeatures()
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
callback(new Image<Rgb24>(ScreenSize.X, ScreenSize.Y));
|
||||
}
|
||||
|
||||
public IClydeViewport CreateViewport()
|
||||
public IClydeViewport CreateViewport(Vector2i size, string? name = null)
|
||||
{
|
||||
return new Viewport();
|
||||
}
|
||||
@@ -410,10 +410,8 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
public IRenderTarget RenderTarget { get; } = new DummyRenderTarget(Vector2i.One, new DummyTexture(Vector2i.One));
|
||||
|
||||
public IEye Eye { get; set; }
|
||||
public void Resize(Vector2i newSize)
|
||||
{
|
||||
}
|
||||
public IEye? Eye { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Robust.Client.Graphics
|
||||
/// <summary>
|
||||
/// The size of the texture, in pixels.
|
||||
/// </summary>
|
||||
public Vector2i Size { get; }
|
||||
public Vector2i Size { get; /*protected set;*/ }
|
||||
|
||||
protected Texture(Vector2i size)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user