#15 Introduce Text Renderer - #145
Conversation
Doesn't work quite yet
Everything after this point needs to have a structure and proper planning. It's been a wild west until now
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Unresolved critical and moderate rendering, atlas, API, cross-platform, and integration issues block approval.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 4
Open (24)
Provide cross-platform vector text extraction · New Pack glyph bitmaps using stored dimensions · New Encode and clamp SDF values around 0.5 · New Make FontGlyphExtractor constructible by consumers · New TextElement does not inherit from GameObject · New Rebuild text resources when properties change · New Apply the public text Color property · New Advance glyph position for outline-less characters · New Text mesh uses an inactive renderer · New Implement signed winding for contour holes · New Avoid duplicate initialization on window attachment · New Remove deleted text elements from the renderer cache · New Prevent duplicate rendering by UI and text renderers · New Enable alpha blending in the text render pass · New Log advance-width fallback failures · New Rename misspelled public enum member Opague · New Initialize the text element logger · New Log font preloading failures · New Log tessellation failures before fallback · New Log font-file fallback failures · New
And 4 more that still need to be addressed.
What changed in this PR
Introduces a text-rendering subsystem with glyph extraction, tessellation, bitmap/vector rendering, caching, shaders, and sample integration. Tests were not run.
Changes:
- Adds
SharpEngine.Text, text entities, font handling, glyph utilities, and renderers. - Adds text shaders, atlas/SDF support, texture caching, and project wiring.
- Refactors UI, audio, resources, numerics, namespaces, examples, and tests.
| File | Reviewed change |
|---|---|
Tests/SharpEngine.Core.UI.Text.Tests/SharpEngine.Core.UI.Text.Tests.csproj |
Adds text test project dependencies. |
Tests/SharpEngine.Core.UI.Text.Tests/GlyphTests.cs |
Adds glyph triangulation test scaffolding. |
Tests/SharpEngine.Core.UI.Text.Tests/GeometryUtilsTests.cs |
Adds geometry test scaffolding. |
Tests/SharpEngine.Core.Tests/SharpEngine.Core.Tests.csproj |
Updates test project dependencies. |
Tests/SharpEngine.Core.ArchitectureTests/GameObjectTests.cs |
Cleans formatting. |
Tests/ObjLoader.Test/SharpEngine.Core.ObjLoader.Tests.csproj |
Removes a duplicate project reference. |
SharpEngine.Text/TypographyGlyphExtractor.cs |
Adds Typography font extraction. |
SharpEngine.Text/Translator.cs |
Converts font commands to glyph segments. |
SharpEngine.Text/TextTextureCache.cs |
Adds runtime text texture caching. |
SharpEngine.Text/TextRenderer.cs |
Adds scene text rendering. |
SharpEngine.Text/SharpEngine.Core.UI.Text.csproj |
Adds text project dependencies. |
SharpEngine.Text/SegmentType.cs |
Defines glyph segment types. |
SharpEngine.Text/Glyphs/GlyphSegment.cs |
Represents glyph outline segments. |
SharpEngine.Text/Glyphs/GlyphMetricsExtractor.cs |
Extracts glyph outlines and metrics. |
SharpEngine.Text/Glyphs/GlyphMeshCache.cs |
Adds glyph mesh caching. |
SharpEngine.Text/Glyphs/GlyphAtlasExtensions.cs |
Builds runtime atlas textures. |
SharpEngine.Text/Glyphs/GlyphAtlas.cs |
Adds atlas packing and SDF generation. |
SharpEngine.Text/Glyphs/Glyph.cs |
Adds glyph triangulation. |
SharpEngine.Text/GeometryUtils.cs |
Adds Bézier and polygon utilities. |
SharpEngine.Text/Fonts/FontManager.cs |
Adds font loading and lookup. |
SharpEngine.Text/Fonts/FontGlyphExtractor.cs |
Adds font outline extraction. |
SharpEngine.Text/Fonts/Font.cs |
Adds font metadata abstraction. |
SharpEngine.Text/Entities/TextElement.cs |
Adds renderable text scene elements. |
SharpEngine.Text/BitMapExtensions.cs |
Adds bitmap text rendering. |
SharpEngine.slnx |
Registers projects and reorganizes solution folders. |
SharpEngine.Core/Windowing/Window.cs |
Updates path helper usage. |
SharpEngine.Core/SharpEngine.Core.csproj |
Updates dependencies and shader resources. |
SharpEngine.Core/Shaders/LightingShader.cs |
Updates default resource references. |
SharpEngine.Core/Shaders/LampShader.cs |
Updates default resource references. |
SharpEngine.Core/Shaders/DefaultShader.cs |
Updates default resource references. |
SharpEngine.Core/Scenes/SceneNode.cs |
Simplifies scene references. |
SharpEngine.Core/Renderers/TextRenderer.cs |
Removes the placeholder renderer. |
SharpEngine.Core/Primitives/PrimitiveFactory.cs |
Updates default resource usage. |
SharpEngine.Core/Primitives/Plane.cs |
Corrects plane UVs. |
SharpEngine.Core/Primitives/Cube.cs |
Updates default texture usage. |
SharpEngine.Core/InputManager.cs |
Clarifies vector type usage. |
SharpEngine.Core/Extensions/PathExtensions.cs |
Removes the moved path helper. |
SharpEngine.Core/Entities/MaterialExtensions.cs |
Extracts material helpers. |
SharpEngine.Core/Entities/Lights/DirectionalLight.cs |
Updates default shader usage. |
SharpEngine.Core/Entities/GameObject.cs |
Updates renderer and resource namespaces. |
SharpEngine.Core/Entities/Components/MeshRenderer.cs |
Moves the renderer namespace. |
SharpEngine.Core/_Resources/Shaders/ui_sdf.vert |
Adds the UI SDF vertex shader. |
SharpEngine.Core/_Resources/Shaders/ui_sdf.frag |
Adds the UI SDF fragment shader. |
SharpEngine.Core/_Resources/Shaders/text-sdf.vert |
Adds the text SDF vertex shader. |
SharpEngine.Core/_Resources/Shaders/text-sdf.frag |
Adds the text SDF fragment shader. |
SharpEngine.Core/_Resources/Shaders/text-curve.vert |
Adds the curve text vertex shader. |
SharpEngine.Core/_Resources/Shaders/text-curve.frag |
Adds a curve text fragment shader placeholder. |
SharpEngine.Core/_Resources/Shaders/text-bitmap.vert |
Adds the bitmap text vertex shader. |
SharpEngine.Core/_Resources/Shaders/text-bitmap.frag |
Adds the bitmap text fragment shader. |
SharpEngine.Core.UI/SharpEngine.Core.UI.csproj |
Adds the UI project definition. |
SharpEngine.Core.UI/Shaders/UIShader.cs |
Updates UI resource usage. |
SharpEngine.Core.UI/Renderers/UIRenderer.cs |
Moves the UI renderer namespace. |
SharpEngine.Core.UI/Renderers/ParticleRenderer.cs |
Moves the particle renderer namespace. |
SharpEngine.Core.UI/Handlers/ParticleEmitter.cs |
Updates UI handler imports. |
SharpEngine.Core.UI/Entities/UIElement.cs |
Moves the UI element namespace. |
SharpEngine.Core.UI/Entities/Layouts/LayoutBase.cs |
Moves the layout namespace. |
SharpEngine.Core.UI/Entities/Layouts/GridLayout.cs |
Moves the grid layout namespace. |
SharpEngine.Core.UI/Entities/Layouts/FlexLayout.cs |
Moves the flex layout namespace. |
SharpEngine.Core.UI/Entities/DraggableUIElement.cs |
Moves the draggable UI namespace. |
SharpEngine.Core.Physics/SharpEngine.Core.Physics.csproj |
Adds the physics project definition. |
SharpEngine.Core.Numerics/Vector3_Intrinsics.cs |
Refactors vector implementation namespaces. |
SharpEngine.Core.Numerics/Vector2.cs |
Refactors vector implementation namespaces. |
SharpEngine.Core.Numerics/Noise/PerlinNoiseGenerator.cs |
Disambiguates math calls. |
SharpEngine.Core.Numerics/Math.cs |
Adds core math helpers. |
SharpEngine.Core.DependencyInjection/WindowServiceCollectionExtensions.cs |
Updates input manager access. |
SharpEngine.Core.Defaults/SharpEngine.Core.Defaults.csproj |
Adds the defaults project definition. |
SharpEngine.Core.Defaults/Defaults.cs |
Moves default resources and adds font paths. |
SharpEngine.Core.Components/SharpEngine.Core.Components.csproj |
Adds component project metadata. |
SharpEngine.Core.Components/Properties/Transform2D.cs |
Enables 2D rotation. |
SharpEngine.Core.Components/Properties/Textures/TextureRuntime.cs |
Adds runtime texture construction. |
SharpEngine.Core.Components/IComponent.cs |
Removes a duplicate component interface. |
SharpEngine.Core.Audio/SharpEngine.Core.Audio.csproj |
Adds the audio project definition. |
SharpEngine.Core.Audio/Players/WavPlayer.cs |
Moves the WAV player namespace. |
SharpEngine.Core.Audio/Players/Mp3Player.cs |
Moves the MP3 player namespace. |
SharpEngine.Core.Audio/AudioSource.cs |
Adds an OpenAL audio source. |
SharpEngine.Core.Audio/AudioProperties.cs |
Adds audio playback properties. |
SharpEngine.Core.Audio/AudioPlayerBase.cs |
Updates audio player imports. |
SharpEngine.Core.Audio/AudioFileExtensions.cs |
Adds audio extension constants. |
SharpEngine.Core.Audio/AudioDevice.cs |
Adds OpenAL device management. |
SharpEngine.Core.Audio/AudioData.cs |
Adds an audio metadata model. |
SharpEngine.Core.Audio/AudioBuffer.cs |
Cleans audio buffer formatting. |
SharpEngine.Core.Audio/Audio.cs |
Updates player namespace usage. |
Examples/Tutorial 4.1 - Model Loading/Tutorial 4.1 - Model Loading.csproj |
Removes a duplicate project reference. |
Examples/Tutorial 4.1 - Model Loading/Program.cs |
Updates default resource usage. |
Examples/MultipleWindows/Program.cs |
Updates vector conversion. |
Examples/MinecraftClone/Terrain/Block/Wood.cs |
Updates defaults namespace usage. |
Examples/MinecraftClone/Terrain/Block/Stone.cs |
Updates defaults namespace usage. |
Examples/MinecraftClone/Terrain/Block/Leaf.cs |
Updates defaults namespace usage. |
Examples/MinecraftClone/Terrain/Block/Iron.cs |
Updates defaults namespace usage. |
Examples/MinecraftClone/Terrain/Block/Grass.cs |
Updates defaults namespace usage. |
Examples/MinecraftClone/Terrain/Block/Dirt.cs |
Updates defaults namespace usage. |
Examples/MinecraftClone/Terrain/Block/BlockBase.cs |
Simplifies vector conversion. |
Examples/MinecraftClone/Program.cs |
Updates renderer namespace imports. |
Examples/MinecraftClone/Minecraft.csproj |
References UI and text projects. |
Examples/MinecraftClone/Minecraft.cs |
Adds text rendering example usage. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if (!OperatingSystem.IsWindows()) | ||
| { | ||
| // On non-Windows platforms, skip the System.Drawing raster path. | ||
| // The vector path or other rendering approaches (SDF, external renderer) should be used instead. | ||
| return; |
| // For prototype we assume glyph metadata contains width/height encoded in name as name|w|h | ||
| var parts = name.Split('|'); | ||
| var w = int.Parse(parts[1]); | ||
| var h = int.Parse(parts[2]); |
| var dist = System.Math.Sqrt(bestDistSq); | ||
| // positive outside distances, negative inside distances | ||
| sdf[idx] = (float)(dist / spread / 2.0 + 0.5) * (inside ? -1 : 1); |
| private readonly ILogger? _logger; | ||
| private readonly IFileSystem _fileSystem; | ||
|
|
||
| internal TypographyGlyphExtractor(ILogger? logger = null, IFileSystem? fileSystem = null) |
| /// Uses UIElement as a base so it can reuse the UI mesh/shader for textured quads. | ||
| /// This implementation draws the text into a bitmap and uploads it as a texture on initialization. | ||
| /// </summary> | ||
| public class TextElement : UIElement |
| catch | ||
| { | ||
| fam = null; | ||
| } |
| try | ||
| { | ||
| kv.Value.tex?.Dispose(); | ||
| } | ||
| catch { } |
| catch | ||
| { | ||
| return typeface.CalculateScaleToPixel(fontSize); | ||
| } |
|
|
||
| public class GeometryUtilsTests | ||
| { | ||
| /*[Fact] |
| var contour = new List<GlyphSegment> | ||
| { | ||
| // TODO: Resolve package reference conflict with System.Numerics. | ||
| // new GlyphSegment(SegmentType.Line, new Vector2(0,0), new Vector2(1,0)), | ||
| // new GlyphSegment(SegmentType.Line, new Vector2(1,0), new Vector2(1,1)), | ||
| // new GlyphSegment(SegmentType.Line, new Vector2(1,1), new Vector2(0,1)), | ||
| // new GlyphSegment(SegmentType.Line, new Vector2(0,1), new Vector2(0,0)), | ||
| }; | ||
|
|
||
| g.AddContour(contour); | ||
|
|
||
| var tris = g.Triangulate(); | ||
| // Should emit at least one triangle (3 verts) | ||
| Assert.True(tris != null); |
|
After this PR goes in I'm doing a full pass of the application and making sure sonar cloud gets an A for all stats with all unit tests passing |






#15 Introduce Text Renderer
Contents
This PR is trying to resolve:
TBD
We resolve it by:
TBD
Checklist
mainto my branch.