Skip to content

Commit

Permalink
Yes
Browse files Browse the repository at this point in the history
  • Loading branch information
notquitehadouken committed Jan 23, 2025
1 parent e03aec4 commit 69172ac
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 37 deletions.
20 changes: 10 additions & 10 deletions Robust.Client/GameObjects/Components/Renderable/SpriteComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,7 @@ public bool SnapCardinals
[ViewVariables(VVAccess.ReadWrite)]
public bool NoRotation { get => _screenLock; set => _screenLock = value; }

internal void RenderInternal(DrawingHandleWorld drawingHandle, Angle eyeRotation, Angle worldRotation, Vector2 worldPosition, Direction? overrideDirection)
internal void RenderInternal(DrawingHandleWorld drawingHandle, Angle eyeRotation, Angle worldRotation, Vector2 worldPosition, Direction? overrideDirection, bool normal = false)
{
var angle = worldRotation + eyeRotation; // angle on-screen. Used to decide the direction of 4/8 directional RSIs
angle = angle.Reduced().FlipPositive(); // Reduce the angles to fix math shenanigans
Expand Down Expand Up @@ -1324,16 +1324,16 @@ internal void RenderInternal(DrawingHandleWorld drawingHandle, Angle eyeRotation
switch (layer.RenderingStrategy)
{
case LayerRenderingStrategy.NoRotation:
layer.Render(drawingHandle, ref transformNoRot, angle, overrideDirection);
layer.Render(drawingHandle, ref transformNoRot, angle, overrideDirection, normal: normal);
break;
case LayerRenderingStrategy.SnapToCardinals:
layer.Render(drawingHandle, ref transformSnap, angle, overrideDirection);
layer.Render(drawingHandle, ref transformSnap, angle, overrideDirection, normal: normal);
break;
case LayerRenderingStrategy.Default:
layer.Render(drawingHandle, ref transformDefault, angle, overrideDirection);
layer.Render(drawingHandle, ref transformDefault, angle, overrideDirection, normal: normal);
break;
case LayerRenderingStrategy.UseSpriteStrategy:
layer.Render(drawingHandle, ref transformSprite, angle, overrideDirection);
layer.Render(drawingHandle, ref transformSprite, angle, overrideDirection, normal: normal);
break;
default:
Logger.Error($"Tried to render a layer with unknown rendering stragegy: {layer.RenderingStrategy}");
Expand All @@ -1346,7 +1346,7 @@ internal void RenderInternal(DrawingHandleWorld drawingHandle, Angle eyeRotation
{
foreach (var layer in Layers)
{
layer.Render(drawingHandle, ref transformSprite, angle, overrideDirection);
layer.Render(drawingHandle, ref transformSprite, angle, overrideDirection, normal: normal);
}
}
}
Expand Down Expand Up @@ -2017,7 +2017,7 @@ public static RsiDirection GetDirection(RsiDirectionType dirType, Angle angle)
/// <summary>
/// Render a layer. This assumes that the input angle is between 0 and 2pi.
/// </summary>
internal void Render(DrawingHandleWorld drawingHandle, ref Matrix3x2 spriteMatrix, Angle angle, Direction? overrideDirection)
internal void Render(DrawingHandleWorld drawingHandle, ref Matrix3x2 spriteMatrix, Angle angle, Direction? overrideDirection, bool normal = false)
{
if (!Visible || Blank)
return;
Expand All @@ -2042,7 +2042,7 @@ internal void Render(DrawingHandleWorld drawingHandle, ref Matrix3x2 spriteMatri
var transformMatrix = Matrix3x2.Multiply(layerMatrix, spriteMatrix);
drawingHandle.SetTransform(in transformMatrix);

RenderTexture(drawingHandle, texture);
RenderTexture(drawingHandle, texture, normal: normal);
}
else
{
Expand Down Expand Up @@ -2072,7 +2072,7 @@ internal void Render(DrawingHandleWorld drawingHandle, ref Matrix3x2 spriteMatri
}
}

private void RenderTexture(DrawingHandleWorld drawingHandle, Texture texture)
private void RenderTexture(DrawingHandleWorld drawingHandle, Texture texture, bool normal = false)
{
if (Shader != null)
drawingHandle.UseShader(Shader);
Expand All @@ -2081,7 +2081,7 @@ private void RenderTexture(DrawingHandleWorld drawingHandle, Texture texture)
var textureSize = texture.Size / (float)EyeManager.PixelsPerMeter;
var quad = Box2.FromDimensions(textureSize/-2, textureSize);

drawingHandle.DrawTextureRectRegion(texture, quad, layerColor);
drawingHandle.DrawTextureRectRegion(texture, quad, layerColor, normal: normal);

if (Shader != null)
drawingHandle.UseShader(null);
Expand Down
4 changes: 2 additions & 2 deletions Robust.Client/GameObjects/EntitySystems/SpriteSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ public sealed partial class SpriteSystem : EntitySystem

private ISawmill _sawmill = default!;

internal void Render(EntityUid uid, SpriteComponent sprite, DrawingHandleWorld drawingHandle, Angle eyeRotation, in Angle worldRotation, in Vector2 worldPosition)
internal void Render(EntityUid uid, SpriteComponent sprite, DrawingHandleWorld drawingHandle, Angle eyeRotation, in Angle worldRotation, in Vector2 worldPosition, bool normal = false)
{
if (!sprite.IsInert)
_queuedFrameUpdate.Add(uid);

sprite.RenderInternal(drawingHandle, eyeRotation, worldRotation, worldPosition, sprite.EnableDirectionOverride ? sprite.DirectionOverride : null);
sprite.RenderInternal(drawingHandle, eyeRotation, worldRotation, worldPosition, sprite.EnableDirectionOverride ? sprite.DirectionOverride : null, normal: normal);
}

public override void Initialize()
Expand Down
18 changes: 15 additions & 3 deletions Robust.Client/Graphics/Clyde/Clyde.HLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ private List<Overlay> GetOverlaysForSpace(OverlaySpace space)
return ScreenBufferTexture;
}

private void DrawEntities(Viewport viewport, Box2Rotated worldBounds, Box2 worldAABB, IEye eye)
private void DrawEntities(Viewport viewport, Box2Rotated worldBounds, Box2 worldAABB, IEye eye, bool normal = false)
{
var mapId = eye.Position.MapId;
if (mapId == MapId.Nullspace)
Expand Down Expand Up @@ -288,7 +288,7 @@ private void DrawEntities(Viewport viewport, Box2Rotated worldBounds, Box2 world
}

Vector2i roundedPos = default;
if (entry.Sprite.PostShader != null)
if (entry.Sprite.PostShader != null && !normal)
{
// get the size of the sprite on screen, scaled slightly to allow for shaders that increase the final sprite size.
var screenSpriteSize = (Vector2i)(entry.SpriteScreenBB.Size * PostShadeScale).Rounded();
Expand Down Expand Up @@ -353,7 +353,13 @@ private void DrawEntities(Viewport viewport, Box2Rotated worldBounds, Box2 world
}
}

spriteSystem.Render(entry.Uid, entry.Sprite, _renderHandle.DrawingHandleWorld, eye.Rotation, in entry.WorldRot, in entry.WorldPos);
spriteSystem.Render(entry.Uid,
entry.Sprite,
_renderHandle.DrawingHandleWorld,
eye.Rotation,
in entry.WorldRot,
in entry.WorldPos,
normal: normal);

if (entry.Sprite.PostShader != null && entityPostRenderTarget != null)
{
Expand Down Expand Up @@ -481,6 +487,12 @@ private void RenderViewport(Viewport viewport)

if (eye.Position.MapId != MapId.Nullspace)
{
using (DebugGroup("EntityNormals"))
using (_prof.Group("EntityNormals"))
{
DrawEntities(viewport, worldBounds, worldAABB, eye, normal: true);
}

using (DebugGroup("Lights"))
using (_prof.Group("Lights"))
{
Expand Down
20 changes: 12 additions & 8 deletions Robust.Client/Graphics/Clyde/Clyde.RenderHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ public void DrawTextureScreen(Texture texture, Vector2 bl, Vector2 br, Vector2 t
/// <param name="modulate">A color to multiply the texture by when shading.</param>
/// <param name="subRegion">The four corners of the texture sub region in px.</param>
public void DrawTextureWorld(Texture texture, Vector2 bl, Vector2 br, Vector2 tl, Vector2 tr,
Color modulate, in UIBox2? subRegion)
Color modulate, in UIBox2? subRegion, bool normal = false)
{
var clydeTexture = ExtractTexture(texture, in subRegion, out var csr);
var clydeTexture = ExtractTexture(texture, in subRegion, out var csr, normal: normal);

var sr = WorldTextureBoundsToUV(clydeTexture, csr);

Expand All @@ -102,14 +102,17 @@ internal static Box2 WorldTextureBoundsToUV(ClydeTexture texture, UIBox2 csr)
/// <summary>
/// Converts a subRegion (px) into texture coords (0-1) of a given texture (cells of the textureAtlas).
/// </summary>
internal static ClydeTexture ExtractTexture(Texture texture, in UIBox2? subRegion, out UIBox2 sr)
internal static ClydeTexture ExtractTexture(Texture texture, in UIBox2? subRegion, out UIBox2 sr, bool normal = false)
{
normal = false;
if (texture is AtlasTexture atlas)
{
texture = atlas.SourceTexture;
if (subRegion.HasValue)
{
var offset = atlas.SubRegion.TopLeft;
if (normal)
offset += Vector2.UnitX * (texture.Width >> 1);
sr = new UIBox2(
subRegion.Value.TopLeft + offset,
subRegion.Value.BottomRight + offset);
Expand All @@ -121,7 +124,8 @@ internal static ClydeTexture ExtractTexture(Texture texture, in UIBox2? subRegio
}
else
{
sr = subRegion ?? new UIBox2(0, 0, texture.Width, texture.Height);
var normOffset = normal ? texture.Width >> 1 : 0;
sr = subRegion ?? new UIBox2(normOffset, 0, texture.Width >> 1 + normOffset, texture.Height);
}

var clydeTexture = (ClydeTexture) texture;
Expand Down Expand Up @@ -513,12 +517,12 @@ public override void DrawRect(in Box2Rotated rect, Color color, bool filled = tr
/// <param name="modulate">A color to multiply the texture by when shading.</param>
/// <param name="subRegion">The four corners of the texture sub region in px.</param>
public override void DrawTextureRectRegion(Texture texture, Box2 quad,
Color? modulate = null, UIBox2? subRegion = null)
Color? modulate = null, UIBox2? subRegion = null, bool normal = false)
{
var color = (modulate ?? Color.White) * Modulate;

_renderHandle.DrawTextureWorld(texture, quad.BottomLeft, quad.BottomRight,
quad.TopLeft, quad.TopRight, color, in subRegion);
quad.TopLeft, quad.TopRight, color, in subRegion, normal: normal);
}

/// <summary>
Expand All @@ -531,12 +535,12 @@ public override void DrawTextureRectRegion(Texture texture, Box2 quad,
/// <param name="modulate">A color to multiply the texture by when shading.</param>
/// <param name="subRegion">The four corners of the texture sub region in px.</param>
public override void DrawTextureRectRegion(Texture texture, in Box2Rotated quad,
Color? modulate = null, UIBox2? subRegion = null)
Color? modulate = null, UIBox2? subRegion = null, bool normal = false)
{
var color = (modulate ?? Color.White) * Modulate;

_renderHandle.DrawTextureWorld(texture, quad.BottomLeft, quad.BottomRight,
quad.TopLeft, quad.TopRight, color, in subRegion);
quad.TopLeft, quad.TopRight, color, in subRegion, normal: normal);
}

public override void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, Texture texture,
Expand Down
4 changes: 2 additions & 2 deletions Robust.Client/Graphics/Drawing/DrawingHandleWorld.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ protected DrawingHandleWorld(Texture white) : base(white)
/// <param name="modulate">A color to multiply the texture by when shading.</param>
/// <param name="subRegion">The four corners of the texture sub region in px.</param>
public abstract void DrawTextureRectRegion(Texture texture, Box2 quad,
Color? modulate = null, UIBox2? subRegion = null);
Color? modulate = null, UIBox2? subRegion = null, bool normal = false);

/// <summary>
/// Draws a sprite to the world. The coordinate system is right handed.
Expand All @@ -56,7 +56,7 @@ public abstract void DrawTextureRectRegion(Texture texture, Box2 quad,
/// <param name="modulate">A color to multiply the texture by when shading.</param>
/// <param name="subRegion">The four corners of the texture sub region in px.</param>
public abstract void DrawTextureRectRegion(Texture texture, in Box2Rotated quad,
Color? modulate = null, UIBox2? subRegion = null);
Color? modulate = null, UIBox2? subRegion = null, bool normal = false);

private Box2 GetQuad(Texture texture, Vector2 position)
{
Expand Down
50 changes: 41 additions & 9 deletions Robust.Client/ResourceManagement/ResourceTypes/RSIResource.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.IsolatedStorage;
using System.Linq;
using Robust.Client.Graphics;
using Robust.Client.Utility;
using Robust.Shared.ContentPack;
using Robust.Shared.Graphics;
using Robust.Shared.Graphics.RSI;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Resources;
using Robust.Shared.Utility;
Expand Down Expand Up @@ -92,14 +95,39 @@ internal static void LoadPreTexture(IResourceManager manager, LoadStepData data)
var stateObject = metadata.States[index];
// Load image from disk.
var texPath = data.Path / (stateObject.StateId + ".png");
var normalPath = data.Path / (stateObject.NormalId + ".png");
using (var stream = manager.ContentFileRead(texPath))
{
reg.Src = Image.Load<Rgba32>(stream);
}
var texture = Image.Load<Rgba32>(stream);
Image<Rgba32> normalImage;
if (stateObject.NormalId is not null)
{
using (var normalStream = manager.ContentFileRead(normalPath))
{
normalImage = Image.Load<Rgba32>(normalStream);
}
}
else
{
normalImage = new Image<Rgba32>(texture.Width, texture.Height);
}
for (int nX = 0; nX < texture.Width; nX++)
{
for (int nY = 0; nY < texture.Height; nY++)
{
var T = normalImage[nX, nY];
if (stateObject.NormalId is not { })
T = new Rgba32(0.5f, 0.5f, 1f, 0f);
T.A = texture[nX, nY].A;
normalImage[nX, nY] = T;
}
}

if (reg.Src.Width % frameSize.X != 0 || reg.Src.Height % frameSize.Y != 0)
reg.Src = (texture, normalImage);
}
if (reg.Src.Item1.Width % frameSize.X != 0 || reg.Src.Item1.Height % frameSize.Y != 0)
{
var regDims = $"{reg.Src.Width}x{reg.Src.Height}";
var regDims = $"{reg.Src.Item1.Width}x{reg.Src.Item1.Height}";
var iconDims = $"{frameSize.X}x{frameSize.Y}";
throw new RSILoadException($"State '{stateObject.StateId}' image size ({regDims}) is not a multiple of the icon size ({iconDims}).");
}
Expand Down Expand Up @@ -144,7 +172,8 @@ internal static void LoadPreTexture(IResourceManager manager, LoadStepData data)
var dimensionX = (int) MathF.Ceiling(MathF.Sqrt(totalFrameCount));
var dimensionY = (int) MathF.Ceiling((float) totalFrameCount / dimensionX);

var sheet = new Image<Rgba32>(dimensionX * frameSize.X, dimensionY * frameSize.Y);
var sheetHalfWidth = dimensionX * frameSize.X;
var sheet = new Image<Rgba32>(sheetHalfWidth * 1, dimensionY * frameSize.Y);

var sheetIndex = 0;
for (var index = 0; index < toAtlas.Length; index++)
Expand All @@ -153,18 +182,20 @@ internal static void LoadPreTexture(IResourceManager manager, LoadStepData data)
// Blit all the frames over.
for (var i = 0; i < reg.TotalFrameCount; i++)
{
var srcWidth = (reg.Src.Width / frameSize.X);
var srcWidth = (reg.Src.Item1.Width / frameSize.X);
var srcColumn = i % srcWidth;
var srcRow = i / srcWidth;
var srcPos = (srcColumn * frameSize.X, srcRow * frameSize.Y);

var sheetColumn = (sheetIndex + i) % dimensionX;
var sheetRow = (sheetIndex + i) / dimensionX;
var sheetPos = (sheetColumn * frameSize.X, sheetRow * frameSize.Y);
var sheetNPos = (sheetColumn * frameSize.X + sheetHalfWidth, sheetRow * frameSize.Y);

var srcBox = UIBox2i.FromDimensions(srcPos, frameSize);

reg.Src.Blit(srcBox, sheet, sheetPos);
reg.Src.Item1.Blit(srcBox, sheet, sheetPos);
// reg.Src.Item2.Blit(srcBox, sheet, sheetNPos);
}

sheetIndex += reg.TotalFrameCount;
Expand All @@ -173,7 +204,8 @@ internal static void LoadPreTexture(IResourceManager manager, LoadStepData data)
for (var i = 0; i < toAtlas.Length; i++)
{
ref var reg = ref toAtlas[i];
reg.Src.Dispose();
reg.Src.Item1.Dispose();
reg.Src.Item2.Dispose();
}

data.Rsi = rsi;
Expand Down Expand Up @@ -392,7 +424,7 @@ internal sealed class LoadStepData

internal struct StateReg
{
public Image<Rgba32> Src;
public (Image<Rgba32>, Image<Rgba32>) Src;
public Texture[][] Output;
public int[][] Indices;
public Vector2i[][] Offsets;
Expand Down
Loading

0 comments on commit 69172ac

Please sign in to comment.