mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Start of msdf text
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
Texture2D<float3> Texture : register(t0);
|
||||||
|
SamplerState Sampler : register(s0);
|
||||||
|
|
||||||
|
cbuffer Constants
|
||||||
|
{
|
||||||
|
float screenPixelRange = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VS_Input
|
||||||
|
{
|
||||||
|
float2 Position : POSITION;
|
||||||
|
float4x4 Tranform : TRANSFORM;
|
||||||
|
float4 Color : COLOR;
|
||||||
|
float4 UVTransform : TEXCOORD;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PS_Input
|
||||||
|
{
|
||||||
|
float4 Position : SV_Position;
|
||||||
|
float2 TexCoord : TEXCOORD0;
|
||||||
|
float4 Color : COLOR;
|
||||||
|
};
|
||||||
|
|
||||||
|
PS_Input VS(VS_Input input)
|
||||||
|
{
|
||||||
|
PS_Input output;
|
||||||
|
|
||||||
|
output.Position = mul(float4(input.Position, 0.0f, 1.0f), input.Tranform);
|
||||||
|
output.TexCoord = input.UVTransform.xy + input.UVTransform.zw * input.Position;
|
||||||
|
output.Color = input.Color;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
float median(float r, float g, float b) {
|
||||||
|
return max(min(r, g), min(max(r, g), b));
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 PS(PS_Input input) : SV_Target0
|
||||||
|
{
|
||||||
|
float3 msd = Texture.Sample(Sampler, input.TexCoord);
|
||||||
|
float sd = median(msd.r, msd.g, msd.b);
|
||||||
|
float screenPxDistance = screenPixelRange * (sd - 0.5);
|
||||||
|
float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0);
|
||||||
|
//color = mix(bgColor, fgColor, opacity);
|
||||||
|
|
||||||
|
//float4 color = lerp(float4(0, 0, 0, 0), input.Color, opacity);
|
||||||
|
|
||||||
|
//return color;
|
||||||
|
|
||||||
|
return float4(input.Color.rgb, opacity * input.Color.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#effect[VS=VS, PS=PS]
|
||||||
+209
-3
@@ -10,6 +10,7 @@ using GlitchyEngine.Math;
|
|||||||
using GlitchyEngine.World;
|
using GlitchyEngine.World;
|
||||||
using GlitchyEngine.Renderer.Text;
|
using GlitchyEngine.Renderer.Text;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using msdfgen;
|
||||||
|
|
||||||
namespace Sandbox
|
namespace Sandbox
|
||||||
{
|
{
|
||||||
@@ -63,6 +64,8 @@ namespace Sandbox
|
|||||||
|
|
||||||
String testText ~ delete _;
|
String testText ~ delete _;
|
||||||
|
|
||||||
|
Effect _msdfEffect ~ _.ReleaseRef();
|
||||||
|
|
||||||
[AllowAppend]
|
[AllowAppend]
|
||||||
public this() : base("Example")
|
public this() : base("Example")
|
||||||
{
|
{
|
||||||
@@ -74,6 +77,7 @@ namespace Sandbox
|
|||||||
|
|
||||||
_effectLibrary.LoadNoRefInc("content\\Shaders\\basicShader.hlsl");
|
_effectLibrary.LoadNoRefInc("content\\Shaders\\basicShader.hlsl");
|
||||||
|
|
||||||
|
|
||||||
// Create rasterizer state
|
// Create rasterizer state
|
||||||
GlitchyEngine.Renderer.RasterizerStateDescription rsDesc = .(.Solid, .Back, true);
|
GlitchyEngine.Renderer.RasterizerStateDescription rsDesc = .(.Solid, .Back, true);
|
||||||
_rasterizerState = new RasterizerState(_context, rsDesc);
|
_rasterizerState = new RasterizerState(_context, rsDesc);
|
||||||
@@ -132,8 +136,184 @@ namespace Sandbox
|
|||||||
// Load test text
|
// Load test text
|
||||||
var result = File.ReadAllText("test.txt", testText = new String(), true);
|
var result = File.ReadAllText("test.txt", testText = new String(), true);
|
||||||
//Log.EngineLogger.Assert(result)
|
//Log.EngineLogger.Assert(result)
|
||||||
|
|
||||||
|
_msdfEffect = _effectLibrary.Load("content\\Shaders\\msdfShader.hlsl");
|
||||||
|
|
||||||
|
DoTheThing(fonty.[Friend]_face, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double F26Dot6ToDouble(uint16 value)
|
||||||
|
{
|
||||||
|
return (double(value) / 64.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoTheThing(FreeType.FT_Face fontFace, double pixelSizeY)
|
||||||
|
{
|
||||||
|
double unitsPerEm = F26Dot6ToDouble(fontFace.units_per_EM);
|
||||||
|
|
||||||
|
// How much we have to scale the geometry to fit it into our desired pixels
|
||||||
|
double geometryScaler = pixelSizeY / unitsPerEm;
|
||||||
|
|
||||||
|
// prepare shape
|
||||||
|
|
||||||
|
double advance = 0;
|
||||||
|
|
||||||
|
var glyphIndex = FreeType.FreeType.Get_Char_Index(fonty.[Friend]_face, 'ß');
|
||||||
|
|
||||||
|
Shape shape;
|
||||||
|
msdfgen.LoadGlyph(out shape, &fonty.[Friend]_face, glyphIndex, out advance);
|
||||||
|
|
||||||
|
shape.Normalize();
|
||||||
|
|
||||||
|
var bounds = shape.GetBounds();
|
||||||
|
|
||||||
|
msdfgen.EdgeColoringSimple(shape, 3.0);
|
||||||
|
|
||||||
|
// prepare projection
|
||||||
|
|
||||||
|
double scale = geometryScaler;
|
||||||
|
double range = 4.0 / geometryScaler;
|
||||||
|
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
|
||||||
|
double translationX;
|
||||||
|
double translationY;
|
||||||
|
|
||||||
|
if(bounds.Left < bounds.Right && bounds.Bottom < bounds.Top)
|
||||||
|
{
|
||||||
|
double l = bounds.Left;
|
||||||
|
double r = bounds.Right;
|
||||||
|
double b = bounds.Bottom;
|
||||||
|
double t = bounds.Top;
|
||||||
|
|
||||||
|
l -= 0.5 * range;
|
||||||
|
b -= 0.5 * range;
|
||||||
|
r += 0.5 * range;
|
||||||
|
t += 0.5 * range;
|
||||||
|
|
||||||
|
// TODO: miter?!
|
||||||
|
|
||||||
|
double w = scale * (r - l);
|
||||||
|
double h = scale * (t - b);
|
||||||
|
|
||||||
|
width = (int)Math.Ceiling(w) + 1;
|
||||||
|
height = (int)Math.Ceiling(h) + 1;
|
||||||
|
|
||||||
|
translationX = -l + 0.5 * (width - w) / scale;
|
||||||
|
translationY = -b + 0.5 * (height - h) / scale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = 0;
|
||||||
|
height = 0;
|
||||||
|
translationX = 0;
|
||||||
|
translationY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
msdfgen.Projection projection = .();
|
||||||
|
projection.ScaleX = scale;
|
||||||
|
projection.ScaleY = scale;
|
||||||
|
|
||||||
|
projection.TranslationX = translationX;
|
||||||
|
projection.TranslationY = translationY;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
void GlyphGeometry::wrapBox(double scale, double range, double miterLimit) {
|
||||||
|
scale *= geometryScale;
|
||||||
|
range /= geometryScale;
|
||||||
|
box.range = range;
|
||||||
|
box.scale = scale;
|
||||||
|
if (bounds.l < bounds.r && bounds.b < bounds.t) {
|
||||||
|
double l = bounds.l, b = bounds.b, r = bounds.r, t = bounds.t;
|
||||||
|
l -= .5*range, b -= .5*range;
|
||||||
|
r += .5*range, t += .5*range;
|
||||||
|
if (miterLimit > 0)
|
||||||
|
shape.boundMiters(l, b, r, t, .5*range, miterLimit, 1);
|
||||||
|
double w = scale*(r-l);
|
||||||
|
double h = scale*(t-b);
|
||||||
|
box.rect.w = (int) ceil(w)+1;
|
||||||
|
box.rect.h = (int) ceil(h)+1;
|
||||||
|
box.translate.x = -l+.5*(box.rect.w-w)/scale;
|
||||||
|
box.translate.y = -b+.5*(box.rect.h-h)/scale;
|
||||||
|
} else {
|
||||||
|
box.rect.w = 0, box.rect.h = 0;
|
||||||
|
box.translate = msdfgen::Vector2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int x = (int)pixelSizeY;
|
||||||
|
int y = (int)pixelSizeY;
|
||||||
|
|
||||||
|
Bitmap<ColorRGB, const 1> bitmap = .((.)x, (.)y);
|
||||||
|
|
||||||
|
MSDFGeneratorConfig config = .();
|
||||||
|
|
||||||
|
msdfgen.GenerateMSDF(*(Bitmap<float, const 3>*)&bitmap, shape, projection, range, config);
|
||||||
|
|
||||||
|
// Save png
|
||||||
|
/*
|
||||||
|
uint8[] data = new uint8[x * y * 3];
|
||||||
|
|
||||||
|
for(int i = 0; i < x * y * 3; i++)
|
||||||
|
{
|
||||||
|
float f = bitmap.Pixels[i / 3].Red / 2f + 0.5f;
|
||||||
|
float f2 = bitmap.Pixels[i / 3].Green / 2f + 0.5f;
|
||||||
|
float f3 = bitmap.Pixels[i / 3].Blue / 2f + 0.5f;
|
||||||
|
|
||||||
|
data[i++] = (uint8)Math.Clamp(256.0f * f, 0, 255);
|
||||||
|
data[i++] = (uint8)Math.Clamp(256.0f * f2, 0, 255);
|
||||||
|
data[i] = (uint8)Math.Clamp(256.0f * f3, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: free shape
|
||||||
|
|
||||||
|
LodePng.LodePng.EncodeFile("test.png", data.Ptr, (.)x, (.)y, .RGB, 8);
|
||||||
|
*/
|
||||||
|
Texture2DDesc desc;
|
||||||
|
desc.Width = (.)x;
|
||||||
|
desc.Height = (.)y;
|
||||||
|
desc.Format = .R8G8B8A8_SNorm;
|
||||||
|
desc.MipLevels = 1;
|
||||||
|
desc.Usage = .Immutable;
|
||||||
|
desc.CpuAccess = .None;
|
||||||
|
desc.ArraySize = 1;
|
||||||
|
|
||||||
|
_dasTestA = new Texture2D(_context, desc);
|
||||||
|
|
||||||
|
int8[] pixels = new int8[x * y * 4];
|
||||||
|
|
||||||
|
int8 ToInt8(float f) => (.)Math.Clamp(127f * f, int8.MinValue, int8.MaxValue);
|
||||||
|
|
||||||
|
//for(int i = 0; i < x * y; i++)
|
||||||
|
for(int iy = 0; iy < y; iy++)
|
||||||
|
for(int ix = 0; ix < x; ix++)
|
||||||
|
{
|
||||||
|
ColorRGB pixel = bitmap.Pixels[iy * y + ix];
|
||||||
|
|
||||||
|
float f = pixel.Red;// / 2f + 0.5f;
|
||||||
|
float f2 = pixel.Green;// / 2f + 0.5f;
|
||||||
|
float f3 = pixel.Blue;// / 2f + 0.5f;
|
||||||
|
|
||||||
|
int index = ((y - iy - 1) * y + ix) * 4;
|
||||||
|
|
||||||
|
pixels[index + 0] = ToInt8(f);
|
||||||
|
pixels[index + 1] = ToInt8(f2);
|
||||||
|
pixels[index + 2] = ToInt8(f3);
|
||||||
|
pixels[index + 3] = 0;
|
||||||
|
|
||||||
|
//pixels[(y - iy - 1) * y + ix] = Color(f, f2, f3);
|
||||||
|
}
|
||||||
|
|
||||||
|
_dasTestA.SetData<Color>((.)pixels.Ptr, 0, 0, (.)x, (.)y);
|
||||||
|
//_dasTestA.SetData<uint8>(pixelData.Ptr, 0, 0, (.)x, (.)y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D _dasTestA ~ _.ReleaseRef();
|
||||||
|
|
||||||
Font fonty ~ _.ReleaseRef();
|
Font fonty ~ _.ReleaseRef();
|
||||||
|
|
||||||
VertexLayout layout ~ _?.ReleaseRef();
|
VertexLayout layout ~ _?.ReleaseRef();
|
||||||
@@ -244,7 +424,7 @@ namespace Sandbox
|
|||||||
movement *= (float)(gameTime.FrameTime.TotalSeconds);
|
movement *= (float)(gameTime.FrameTime.TotalSeconds);
|
||||||
|
|
||||||
cameraTransform.Position += .(movement, 0);
|
cameraTransform.Position += .(movement, 0);
|
||||||
Runtime.NotImplemented();
|
//Runtime.NotImplemented();
|
||||||
//cameraTransform.Update();
|
//cameraTransform.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,6 +432,8 @@ namespace Sandbox
|
|||||||
camera.Aspect = Application.Get().Window.Context.SwapChain.BackbufferViewport.Width /
|
camera.Aspect = Application.Get().Window.Context.SwapChain.BackbufferViewport.Width /
|
||||||
Application.Get().Window.Context.SwapChain.BackbufferViewport.Height;
|
Application.Get().Window.Context.SwapChain.BackbufferViewport.Height;
|
||||||
|
|
||||||
|
TransformSystem.Update(_world);
|
||||||
|
|
||||||
RenderCommand.Clear(null, .(0.2f, 0.2f, 0.2f));
|
RenderCommand.Clear(null, .(0.2f, 0.2f, 0.2f));
|
||||||
|
|
||||||
_depthTarget..Clear(1.0f, 0, .Depth).Bind();
|
_depthTarget..Clear(1.0f, 0, .Depth).Bind();
|
||||||
@@ -313,12 +495,26 @@ namespace Sandbox
|
|||||||
_alphaBlendState.Bind();
|
_alphaBlendState.Bind();
|
||||||
Renderer2D.Begin(.FrontToBack, .(_context.SwapChain.Width, _context.SwapChain.Height));
|
Renderer2D.Begin(.FrontToBack, .(_context.SwapChain.Width, _context.SwapChain.Height));
|
||||||
|
|
||||||
|
Renderer2D.Draw(null, 0, 0, 502, 502, .Black, 5);
|
||||||
|
|
||||||
// Hallo Welt, wie geht es dir? 😂😂😂\nMir geht es gut, danke der Nachfrage. Wie geht es dir?\nMir geht es hervorragend und besser noch: meine Engine kann endlich Text rendern!💕❤\n und es scheint ganz in ordnung zu sein.
|
// Hallo Welt, wie geht es dir? 😂😂😂\nMir geht es gut, danke der Nachfrage. Wie geht es dir?\nMir geht es hervorragend und besser noch: meine Engine kann endlich Text rendern!💕❤\n und es scheint ganz in ordnung zu sein.
|
||||||
FontRenderer.DrawText(Renderer2D, fonty, testText, 0, 0, .White, .White, 32);
|
//FontRenderer.DrawText(Renderer2D, fonty, testText, 0, 0, .White, .White, 32);
|
||||||
|
|
||||||
|
Renderer2D.End();
|
||||||
|
|
||||||
|
Renderer2D.Begin(.FrontToBack, .(_context.SwapChain.Width, _context.SwapChain.Height), 100, _msdfEffect);
|
||||||
|
|
||||||
|
_msdfEffect.Variables["screenPixelRange"].SetData(size / 64f * 4.0f);
|
||||||
|
|
||||||
|
Renderer2D.Draw(_dasTestA, 1, 1, size, size);
|
||||||
|
|
||||||
|
// TODO: SDFs in Font Atlas packen
|
||||||
|
|
||||||
Renderer2D.End();
|
Renderer2D.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 size = 500;
|
||||||
|
|
||||||
ColorRGBA _squareColor0 = ColorRGBA.CornflowerBlue;
|
ColorRGBA _squareColor0 = ColorRGBA.CornflowerBlue;
|
||||||
ColorRGBA _squareColor1;
|
ColorRGBA _squareColor1;
|
||||||
|
|
||||||
@@ -333,6 +529,16 @@ namespace Sandbox
|
|||||||
|
|
||||||
private bool OnImGuiRender(ImGuiRenderEvent e)
|
private bool OnImGuiRender(ImGuiRenderEvent e)
|
||||||
{
|
{
|
||||||
|
ImGui.Begin("SDF Test");
|
||||||
|
|
||||||
|
ImGui.InputInt("Size", &size);
|
||||||
|
|
||||||
|
float f = (size / 64f * 4.0f);
|
||||||
|
|
||||||
|
ImGui.Text($"SPR: {f}");
|
||||||
|
|
||||||
|
ImGui.End();
|
||||||
|
/*
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
ImGui.Begin("Test");
|
ImGui.Begin("Test");
|
||||||
@@ -348,7 +554,7 @@ namespace Sandbox
|
|||||||
//ImGui.Image(fonty.[Friend]_atlas.[Friend]nativeView, .(fonty.[Friend]_atlas.Width, fonty.[Friend]_atlas.Height), .(0.0f, 0.0f), .(1.0f, 1.0f), .(1.0f, 1.0f, 1.0f, 1.0f), .(1.0f, 0, 0, 1));
|
//ImGui.Image(fonty.[Friend]_atlas.[Friend]nativeView, .(fonty.[Friend]_atlas.Width, fonty.[Friend]_atlas.Height), .(0.0f, 0.0f), .(1.0f, 1.0f), .(1.0f, 1.0f, 1.0f, 1.0f), .(1.0f, 0, 0, 1));
|
||||||
|
|
||||||
ImGui.End();
|
ImGui.End();
|
||||||
|
*/
|
||||||
TextureViewer();
|
TextureViewer();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user