Add utility function to GUICommon.hlsl for MSDF fonts sampling in shaders
#3944
This commit is contained in:
BIN
Content/Shaders/GUI.flax
LFS
BIN
Content/Shaders/GUI.flax
LFS
Binary file not shown.
@@ -77,7 +77,7 @@ API_ENUM() enum class FontRasterMode : byte
|
||||
Bitmap,
|
||||
|
||||
/// <summary>
|
||||
/// Use the MSDF generator to render font atlases. Need to be rendered with a compatible material.
|
||||
/// Use the Multi-channel Signed Distance Field (MSDF) generator to render font atlases. Need to be rendered with a compatible material.
|
||||
/// </summary>
|
||||
MSDF,
|
||||
};
|
||||
@@ -92,7 +92,7 @@ API_STRUCT() struct FontOptions
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(FontOptions);
|
||||
|
||||
/// <summary>
|
||||
/// The hinting.
|
||||
/// The font hinting used when rendering characters.
|
||||
/// </summary>
|
||||
API_FIELD() FontHinting Hinting;
|
||||
|
||||
@@ -102,7 +102,7 @@ API_STRUCT() struct FontOptions
|
||||
API_FIELD() FontFlags Flags;
|
||||
|
||||
/// <summary>
|
||||
/// The rasterization mode.
|
||||
/// The font rasterization mode.
|
||||
/// </summary>
|
||||
API_FIELD() FontRasterMode RasterMode;
|
||||
};
|
||||
|
||||
@@ -92,7 +92,7 @@ float4 PS_Font(VS2PS input) : SV_Target0
|
||||
PerformClipping(input);
|
||||
|
||||
float4 color = input.Color;
|
||||
color.a *= Image.Sample(SamplerLinearClamp, input.TexCoord).r;
|
||||
color.a *= SampleFont(Image, input.TexCoord);
|
||||
return color;
|
||||
}
|
||||
|
||||
@@ -102,22 +102,8 @@ float4 PS_FontMSDF(VS2PS input) : SV_Target0
|
||||
PerformClipping(input);
|
||||
|
||||
float4 color = input.Color;
|
||||
float3 msd = Image.Sample(SamplerLinearClamp, input.TexCoord).rgb;
|
||||
float sd = max(min(msd.r, msd.g), min(max(msd.r, msd.g), msd.b));
|
||||
|
||||
uint width, height;
|
||||
Image.GetDimensions(width, height);
|
||||
float pxRange = 4.0f; // Must match C++ code
|
||||
float unitRange = float2(pxRange, pxRange) / float2(width, height);
|
||||
|
||||
float2 dx = ddx(input.TexCoord);
|
||||
float2 dy = ddy(input.TexCoord);
|
||||
float2 screenTexSize = rsqrt(dx * dx + dy * dy);
|
||||
float screenPxRange = max(0.5f * dot(screenTexSize, unitRange), 1.0f);
|
||||
float screenPxDist = screenPxRange * (sd - 0.5f);
|
||||
|
||||
float opacity = saturate(screenPxDist + 0.5f);
|
||||
return float4(color.rgb, opacity);
|
||||
color.a *= SampleFontMSDF(Image, input.TexCoord);
|
||||
return color;
|
||||
}
|
||||
|
||||
float4 GetSample(float weight, float offset, float2 uv)
|
||||
|
||||
@@ -54,4 +54,47 @@ void PerformClipping(VS2PS input)
|
||||
PerformClipping(input.ClipOriginAndPos.xy, input.ClipOriginAndPos.zw, input.ClipExtents);
|
||||
}
|
||||
|
||||
float SampleFont(Texture2D font, float2 uv)
|
||||
{
|
||||
return font.Sample(SamplerLinearClamp, uv).r;
|
||||
}
|
||||
|
||||
float GetFontMSDFMedian(Texture2D font, float2 uv)
|
||||
{
|
||||
float4 msd = font.Sample(SamplerLinearClamp, uv);
|
||||
return max(min(msd.r, msd.g), min(max(msd.r, msd.g), msd.b));
|
||||
}
|
||||
|
||||
float GetFontMSDFPixelRange(Texture2D font, float2 uv)
|
||||
{
|
||||
uint width, height;
|
||||
font.GetDimensions(width, height);
|
||||
float pxRange = 4.0f; // Must match C++ code
|
||||
float unitRange = float2(pxRange, pxRange) / float2(width, height);
|
||||
|
||||
float2 dx = ddx(uv);
|
||||
float2 dy = ddy(uv);
|
||||
float2 screenTexSize = rsqrt(dx * dx + dy * dy);
|
||||
return max(0.5f * dot(screenTexSize, unitRange), 1.0f);
|
||||
}
|
||||
|
||||
float SampleFontMSDF(Texture2D font, float2 uv)
|
||||
{
|
||||
float sd = GetFontMSDFMedian(font, uv);
|
||||
float screenPxRange = GetFontMSDFPixelRange(font, uv);
|
||||
float screenPxDist = screenPxRange * (sd - 0.5f);
|
||||
return saturate(screenPxDist + 0.5f);
|
||||
}
|
||||
|
||||
float SampleFontMSDFOutline(Texture2D font, float2 uv, float thickness)
|
||||
{
|
||||
float4 msd = font.Sample(SamplerLinearClamp, uv);
|
||||
float sd = max(min(msd.r, msd.g), min(max(msd.r, msd.g), msd.b));
|
||||
float screenPxRange = GetFontMSDFPixelRange(font, uv);
|
||||
float thick = clamp(thickness, 0.0, screenPxRange * 0.5 - 1.0) / screenPxRange;
|
||||
float outline = saturate((min(sd, msd.a) - 0.5 + thick) * screenPxRange + 0.5);
|
||||
outline *= 1 - saturate(screenPxRange * (sd - 0.5f) + 0.5f);
|
||||
return outline;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user