Skip to content

Commit

Permalink
Merge pull request #166 from andy840119/fix-outline-shader-issue
Browse files Browse the repository at this point in the history
Fix left-side shader showing before first time-tag time.
  • Loading branch information
andy840119 authored May 1, 2022
2 parents 4fd5de5 + ef7acee commit 48173a3
Show file tree
Hide file tree
Showing 12 changed files with 315 additions and 11 deletions.
47 changes: 47 additions & 0 deletions osu.Framework.Font.Tests/Shaders/OutlineShaderTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) karaoke.dev <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using NUnit.Framework;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shaders;

namespace osu.Framework.Font.Tests.Shaders
{
public class OutlineShaderTest
{
[TestCase(10, -5, -5, 30, 30)]
[TestCase(0, 5, 5, 10, 10)]
[TestCase(-10, 5, 5, 10, 10)]
public void TestComputeCharacterDrawRectangle(int radius, float expectedX, float expectedY, float expectedWidth, float expectedHeight)
{
var shader = new OutlineShader
{
Radius = radius
};

var rectangle = shader.ComputeCharacterDrawRectangle(new RectangleF(5, 5, 10, 10));
Assert.AreEqual(expectedX, rectangle.X);
Assert.AreEqual(expectedY, rectangle.Y);
Assert.AreEqual(expectedWidth, rectangle.Width);
Assert.AreEqual(expectedHeight, rectangle.Height);
}

[TestCase(10, -5, -5, 30, 30)]
[TestCase(0, 5, 5, 10, 10)]
[TestCase(-10, 5, 5, 10, 10)]
public void TestComputeScreenSpaceDrawQuad(int radius, float expectedX, float expectedY, float expectedWidth, float expectedHeight)
{
var shader = new OutlineShader
{
Radius = radius
};

var quad = shader.ComputeScreenSpaceDrawQuad(new Quad(5, 5, 10, 10));
var rectangle = quad.AABBFloat;
Assert.AreEqual(expectedX, rectangle.X);
Assert.AreEqual(expectedY, rectangle.Y);
Assert.AreEqual(expectedWidth, rectangle.Width);
Assert.AreEqual(expectedHeight, rectangle.Height);
}
}
}
35 changes: 35 additions & 0 deletions osu.Framework.Font.Tests/Shaders/ShadowShaderTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) karaoke.dev <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using NUnit.Framework;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shaders;
using osuTK;

namespace osu.Framework.Font.Tests.Shaders
{
public class ShadowShaderTest
{
private const float offset_x = 11;
private const float offset_y = 12;

[TestCase(offset_x, 0, 5, 5, 10 + offset_x, 10)] // Offset right
[TestCase(-offset_x, 0, 5 - offset_x, 5, 10 + offset_x, 10)] // Offset left
[TestCase(0, offset_y, 5, 5, 10, 10 + offset_y)] // Offset down
[TestCase(0, -offset_y, 5, 5 - offset_y, 10, 10 + offset_y)] // Offset up
public void TestComputeScreenSpaceDrawQuad(float offsetX, float offsetY, float expectedX, float expectedY, float expectedWidth, float expectedHeight)
{
var shader = new ShadowShader
{
ShadowOffset = new Vector2(offsetX, offsetY)
};

var quad = shader.ComputeScreenSpaceDrawQuad(new Quad(5, 5, 10, 10));
var rectangle = quad.AABBFloat;
Assert.AreEqual(expectedX, rectangle.X);
Assert.AreEqual(expectedY, rectangle.Y);
Assert.AreEqual(expectedWidth, rectangle.Width);
Assert.AreEqual(expectedHeight, rectangle.Height);
}
}
}
136 changes: 136 additions & 0 deletions osu.Framework.Font.Tests/Shaders/StepShaderTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright (c) karaoke.dev <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using NUnit.Framework;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shaders;
using osuTK;

namespace osu.Framework.Font.Tests.Shaders
{
public class StepShaderTest
{
[Test]
public void TestComputeCharacterDrawRectangle()
{
const int outline_radius = 10;
const int shadow_offset_x = 11;
const int shadow_offset_y = 12;

var shader = new StepShader
{
StepShaders = new ICustomizedShader[]
{
new OutlineShader
{
Radius = outline_radius
},
new ShadowShader
{
ShadowOffset = new Vector2(shadow_offset_x, shadow_offset_y)
}
}
};

var rectangle = shader.ComputeCharacterDrawRectangle(new RectangleF(5, 5, 10, 10));
Assert.AreEqual(5 - outline_radius, rectangle.X);
Assert.AreEqual(5 - outline_radius, rectangle.Y);
Assert.AreEqual(10 + outline_radius * 2, rectangle.Width);
Assert.AreEqual(10 + outline_radius * 2, rectangle.Height);
}

[Test]
public void TestComputeScreenSpaceDrawQuad()
{
const int outline_radius = 10;
const int shadow_offset_x = 11;
const int shadow_offset_y = 12;

var shader = new StepShader
{
StepShaders = new ICustomizedShader[]
{
new OutlineShader
{
Radius = outline_radius
},
new ShadowShader
{
ShadowOffset = new Vector2(shadow_offset_x, shadow_offset_y)
}
}
};

var quad = shader.ComputeScreenSpaceDrawQuad(new Quad(5, 5, 10, 10));
var rectangle = quad.AABBFloat;
Assert.AreEqual(5 - outline_radius, rectangle.X);
Assert.AreEqual(5 - outline_radius, rectangle.Y);
Assert.AreEqual(10 + outline_radius * 2 + shadow_offset_x, rectangle.Width);
Assert.AreEqual(10 + outline_radius * 2 + shadow_offset_y, rectangle.Height);
}

[Test]
public void TestComputeCharacterDrawRectangleWithEmptyShader()
{
var shader = new StepShader();

var rectangle = shader.ComputeCharacterDrawRectangle(new RectangleF(5, 5, 10, 10));
Assert.AreEqual(5, rectangle.X);
Assert.AreEqual(5, rectangle.Y);
Assert.AreEqual(10, rectangle.Width);
Assert.AreEqual(10, rectangle.Height);
}

[Test]
public void TestEmptyComputeScreenSpaceDrawQuadWithEmptyShader()
{
var shader = new StepShader();

var quad = shader.ComputeScreenSpaceDrawQuad(new Quad(5, 5, 10, 10));
var rectangle = quad.AABBFloat;
Assert.AreEqual(5, rectangle.X);
Assert.AreEqual(5, rectangle.Y);
Assert.AreEqual(10, rectangle.Width);
Assert.AreEqual(10, rectangle.Height);
}

[Test]
public void TestCharacterDrawRectangleWithNoneMatchedShader()
{
var shader = new StepShader
{
StepShaders = new[]
{
new PixelShader()
}
};

var rectangle = shader.ComputeCharacterDrawRectangle(new RectangleF(5, 5, 10, 10));
Assert.AreEqual(5, rectangle.X);
Assert.AreEqual(5, rectangle.Y);
Assert.AreEqual(10, rectangle.Width);
Assert.AreEqual(10, rectangle.Height);
}

[Test]
public void TestEmptyComputeScreenSpaceDrawQuadNoneMatchedShader()
{
var shader = new StepShader
{
StepShaders = new[]
{
new PixelShader()
}
};

var quad = shader.ComputeScreenSpaceDrawQuad(new Quad(5, 5, 10, 10));
var rectangle = quad.AABBFloat;
Assert.AreEqual(5, rectangle.X);
Assert.AreEqual(5, rectangle.Y);
Assert.AreEqual(10, rectangle.Width);
Assert.AreEqual(10, rectangle.Height);
}
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public TestSceneKaraokeSpriteTextTransforms()

AddLabel("Timing");

AddSliderStep("Adjust clock time", 0, end_time + exrea_time, start_time - exrea_time, time =>
AddSliderStep("Adjust clock time", start_time - exrea_time, end_time + exrea_time, start_time, time =>
{
manualClock.CurrentTime = time;
});
Expand Down
12 changes: 12 additions & 0 deletions osu.Framework.Font/Graphics/Shaders/IApplicableToCharacterSize.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) karaoke.dev <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Graphics.Primitives;

namespace osu.Framework.Graphics.Shaders
{
public interface IApplicableToCharacterSize
{
RectangleF ComputeCharacterDrawRectangle(RectangleF originalCharacterDrawRectangle);
}
}
12 changes: 12 additions & 0 deletions osu.Framework.Font/Graphics/Shaders/IApplicableToDrawQuad.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) karaoke.dev <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Graphics.Primitives;

namespace osu.Framework.Graphics.Shaders
{
public interface IApplicableToDrawQuad
{
Quad ComputeScreenSpaceDrawQuad(Quad originDrawQuad);
}
}
13 changes: 12 additions & 1 deletion osu.Framework.Font/Graphics/Shaders/OutlineShader.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// Copyright (c) karaoke.dev <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using osu.Framework.Graphics.OpenGL.Buffers;
using osu.Framework.Graphics.Primitives;
using osuTK;
using osuTK.Graphics;

namespace osu.Framework.Graphics.Shaders
{
public class OutlineShader : InternalShader
public class OutlineShader : InternalShader, IApplicableToCharacterSize, IApplicableToDrawQuad
{
public override string ShaderName => "Outline";

Expand All @@ -31,5 +33,14 @@ public override void ApplyValue(FrameBuffer current)
var size = current.Size;
GetUniform<Vector2>(@"g_TexSize").UpdateValue(ref size);
}

public RectangleF ComputeCharacterDrawRectangle(RectangleF originalCharacterDrawRectangle)
=> originalCharacterDrawRectangle.Inflate(Math.Max(Radius, 0));

public Quad ComputeScreenSpaceDrawQuad(Quad originDrawQuad)
{
var rectangle = ComputeCharacterDrawRectangle(originDrawQuad.AABBFloat);
return Quad.FromRectangle(rectangle);
}
}
}
17 changes: 16 additions & 1 deletion osu.Framework.Font/Graphics/Shaders/ShadowShader.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// Copyright (c) karaoke.dev <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using osu.Framework.Graphics.OpenGL.Buffers;
using osu.Framework.Graphics.Primitives;
using osuTK;
using osuTK.Graphics;

namespace osu.Framework.Graphics.Shaders
{
public class ShadowShader : InternalShader
public class ShadowShader : InternalShader, IApplicableToDrawQuad
{
public override string ShaderName => "Shadow";

Expand All @@ -26,5 +28,18 @@ public override void ApplyValue(FrameBuffer current)
var size = current.Size;
GetUniform<Vector2>(@"g_TexSize").UpdateValue(ref size);
}

public Quad ComputeScreenSpaceDrawQuad(Quad originDrawQuad)
{
var rectangle = originDrawQuad.AABBFloat.Inflate(new MarginPadding
{
Left = Math.Max(-ShadowOffset.X, 0),
Right = Math.Max(ShadowOffset.X, 0),
Top = Math.Max(-ShadowOffset.Y, 0),
Bottom = Math.Max(ShadowOffset.Y, 0),
});

return Quad.FromRectangle(rectangle);
}
}
}
11 changes: 10 additions & 1 deletion osu.Framework.Font/Graphics/Shaders/StepShader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics.OpenGL.Buffers;
using osu.Framework.Graphics.Primitives;

namespace osu.Framework.Graphics.Shaders
{
public class StepShader : IStepShader
public class StepShader : IStepShader, IApplicableToCharacterSize, IApplicableToDrawQuad
{
public string Name { get; set; }

Expand Down Expand Up @@ -45,5 +46,13 @@ public bool IsLoaded

public void ApplyValue(FrameBuffer current)
=> throw new NotSupportedException();

public RectangleF ComputeCharacterDrawRectangle(RectangleF originalCharacterDrawRectangle) =>
StepShaders.OfType<IApplicableToCharacterSize>()
.Aggregate(originalCharacterDrawRectangle, (rectangle, shader) => shader.ComputeCharacterDrawRectangle(rectangle));

public Quad ComputeScreenSpaceDrawQuad(Quad originDrawQuad) =>
StepShaders.OfType<IApplicableToDrawQuad>()
.Aggregate(originDrawQuad, (quad, shader) => shader.ComputeScreenSpaceDrawQuad(quad));
}
}
Loading

0 comments on commit 48173a3

Please sign in to comment.