Moving a ton of rendering code around and it somehow still works somewhat.

This commit is contained in:
Pieter-Jan Briers
2020-07-13 16:27:43 +02:00
parent 16ba90a654
commit b7e224a56f
13 changed files with 278 additions and 171 deletions
@@ -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);
+93 -51
View File
@@ -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
{
+21 -12
View File
@@ -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
}
}
}
+49 -8
View File
@@ -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));
+3 -3
View File
@@ -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; }
}
}
}
+1 -1
View File
@@ -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)
{