Skip to content

Commit

Permalink
Fix the outline shader.
Browse files Browse the repository at this point in the history
Co-authored-by: WebFreak001 <[email protected]>
  • Loading branch information
andy840119 and WebFreak001 committed Mar 19, 2023
1 parent f9dd06f commit c7a32d6
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 63 deletions.
10 changes: 5 additions & 5 deletions osu.Framework.Font.Tests/Shaders/OutlineShaderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,19 @@ public void CreateGetOutlineMethod(int samples)
const float pi = 3.14159265359f;
double angle = 0.0f;

Console.WriteLine("lowp float outlineAlpha(sampler2D tex, float radius, mediump vec2 texCoord, mediump vec2 texSize)");
Console.WriteLine("lowp float outlineAlpha(in float radius, in mediump vec2 texCoord, in mediump vec2 texSize)");
Console.WriteLine("{");
Console.WriteLine(" mediump vec2 offset = mediump vec2(radius) / texSize;");
Console.WriteLine(" lowp float alpha = 0.0;");
Console.WriteLine(" mediump vec2 offset = vec2(radius) / texSize;");
Console.WriteLine(" lowp float alpha = 0.0;");
Console.WriteLine();

for (int i = 0; i < samples; i++)
{
angle += 1.0 / (samples / 2.0) * pi;
Console.WriteLine($" alpha = max(alpha, texture2D(tex, texCoord - lowp vec2({Math.Sin(angle):N2}, {Math.Cos(angle):N2}) * offset).a);");
Console.WriteLine($" alpha = max(alpha, tex(texCoord - vec2({Math.Sin(angle):N2}, {Math.Cos(angle):N2}) * offset).a);");
}

Console.WriteLine(" return alpha;");
Console.WriteLine(" return alpha;");
Console.WriteLine("}");
}
}
29 changes: 22 additions & 7 deletions osu.Framework.Font/Graphics/Shaders/OutlineShader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Runtime.InteropServices;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Rendering;
using osu.Framework.Graphics.Shaders.Types;
using osuTK;
using osuTK.Graphics;

Expand All @@ -15,25 +17,38 @@ public class OutlineShader : InternalShader, IApplicableToCharacterSize, IApplic

public Color4 Colour { get; set; }

public Color4 OutlineColour { get; set; }

public float Radius { get; set; }

public Color4 OutlineColour { get; set; }
private IUniformBuffer<OutlineParameters>? outlineParametersBuffer;

public override void ApplyValue(IRenderer renderer)
{
var colourMatrix = new Vector4(Colour.R, Colour.G, Colour.B, Colour.A);
GetUniform<Vector4>(@"g_Colour").UpdateValue(ref colourMatrix);
outlineParametersBuffer ??= renderer.CreateUniformBuffer<OutlineParameters>();

float radius = Radius;
GetUniform<float>(@"g_Radius").UpdateValue(ref radius);
outlineParametersBuffer.Data = new OutlineParameters
{
Colour = new Vector4(Colour.R, Colour.G, Colour.B, Colour.A),
OutlineColour = new Vector4(OutlineColour.R, OutlineColour.G, OutlineColour.B, OutlineColour.A),
Radius = Radius,
};

var outlineColourMatrix = new Vector4(OutlineColour.R, OutlineColour.G, OutlineColour.B, OutlineColour.A);
GetUniform<Vector4>(@"g_OutlineColour").UpdateValue(ref outlineColourMatrix);
BindUniformBlock("m_OutlineParameters", outlineParametersBuffer);
}

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

public RectangleF ComputeDrawRectangle(RectangleF originDrawRectangle)
=> ComputeCharacterDrawRectangle(originDrawRectangle);

[StructLayout(LayoutKind.Sequential, Pack = 1)]
private record struct OutlineParameters
{
public UniformVector4 Colour;
public UniformVector4 OutlineColour;
public UniformFloat Radius;
private readonly UniformPadding12 pad1;
}
}
112 changes: 61 additions & 51 deletions osu.Framework.Font/Resources/Shaders/sh_Outline.fs
Original file line number Diff line number Diff line change
@@ -1,66 +1,76 @@
#include "sh_CustomizedShaderGlobalUniforms.h"
#include "sh_Utils.h"

varying mediump vec2 v_TexCoord;
layout(location = 2) in highp vec2 v_TexCoord;

uniform lowp sampler2D m_Sampler;
layout(std140, set = 2, binding = 0) uniform m_OutlineParameters
{
mediump vec4 g_Colour;
mediump vec4 g_OutlineColour;
mediump float g_Radius;
};

layout(set = 1, binding = 0) uniform lowp texture2D m_Texture;
layout(set = 1, binding = 1) uniform lowp sampler m_Sampler;

layout(location = 0) out vec4 o_Colour;

uniform mediump vec2 g_TexSize;
uniform vec4 g_Colour;
uniform float g_Radius;
uniform vec4 g_OutlineColour;
uniform float g_InflationPercentage;
mediump vec4 tex(in mediump vec2 texCoord)
{
return texture(sampler2D(m_Texture, m_Sampler), texCoord);
}

lowp float outlineAlpha(sampler2D tex, float radius, mediump vec2 texCoord, mediump vec2 texSize)
lowp float outlineAlpha(in float radius, in mediump vec2 texCoord, in mediump vec2 texSize)
{
mediump vec2 offset = mediump vec2(radius) / texSize;
lowp float alpha = 0.0;
mediump vec2 offset = vec2(radius) / texSize;
lowp float alpha = 0.0;

alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.20, 0.98) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.38, 0.92) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.56, 0.83) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.71, 0.71) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.83, 0.56) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.92, 0.38) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.98, 0.20) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(1.00, -0.00) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.98, -0.20) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.92, -0.38) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.83, -0.56) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.71, -0.71) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.56, -0.83) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.38, -0.92) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.20, -0.98) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.00, -1.00) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.20, -0.98) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.38, -0.92) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.56, -0.83) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.71, -0.71) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.83, -0.56) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.92, -0.38) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.98, -0.20) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-1.00, 0.00) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.98, 0.20) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.92, 0.38) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.83, 0.56) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.71, 0.71) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.56, 0.83) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.38, 0.92) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(-0.20, 0.98) * offset).a);
alpha = max(alpha, texture2D(tex, texCoord - lowp vec2(0.00, 1.00) * offset).a);
return alpha;
alpha = max(alpha, tex(texCoord - vec2(0.20, 0.98) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.38, 0.92) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.56, 0.83) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.71, 0.71) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.83, 0.56) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.92, 0.38) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.98, 0.20) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(1.00, -0.00) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.98, -0.20) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.92, -0.38) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.83, -0.56) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.71, -0.71) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.56, -0.83) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.38, -0.92) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.20, -0.98) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.00, -1.00) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.20, -0.98) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.38, -0.92) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.56, -0.83) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.71, -0.71) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.83, -0.56) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.92, -0.38) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.98, -0.20) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-1.00, 0.00) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.98, 0.20) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.92, 0.38) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.83, 0.56) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.71, 0.71) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.56, 0.83) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.38, 0.92) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(-0.20, 0.98) * offset).a);
alpha = max(alpha, tex(texCoord - vec2(0.00, 1.00) * offset).a);
return alpha;
}

lowp vec4 outline(sampler2D tex, float radius, mediump vec2 texCoord, mediump vec2 texSize, mediump vec4 colour)
lowp vec4 outline(float radius, mediump vec2 texCoord, mediump vec2 texSize, mediump vec4 colour)
{
lowp float outlineAlpha = max(outlineAlpha(tex, radius, texCoord, texSize), outlineAlpha(tex, radius / 2.0, texCoord, texSize));
return mix(vec4(0.0), colour, outlineAlpha);
lowp float res = max(outlineAlpha(radius, texCoord, texSize), outlineAlpha(radius / 2.0, texCoord, texSize));
return mix(vec4(0.0), colour, res);
}

void main(void)
{
lowp vec4 sample = toSRGB(texture2D(m_Sampler, v_TexCoord));
lowp vec4 originColur = vec4(mix(sample.rgb, g_Colour.rgb, g_Colour.a), sample.a);
lowp vec4 outlineColour = outline(m_Sampler, g_Radius * g_InflationPercentage, v_TexCoord, g_TexSize, g_OutlineColour);
lowp vec4 texColour = toSRGB(texture(sampler2D(m_Texture, m_Sampler), v_TexCoord));
lowp vec4 originColour = vec4(mix(texColour.rgb, g_Colour.rgb, g_Colour.a), texColour.a);
lowp vec4 outlineColour = outline(g_Radius * g_InflationPercentage, v_TexCoord, g_TexSize, g_OutlineColour);

gl_FragColor = mix(outlineColour, originColur, originColur.a);
}
o_Colour = mix(outlineColour, originColour, originColour.a);
}

0 comments on commit c7a32d6

Please sign in to comment.