Skip to content

Add opt-in per-pixel unified outline - #6

Draft
paq wants to merge 1 commit into
ruccho:mainfrom
paq:unified-outline
Draft

Add opt-in per-pixel unified outline#6
paq wants to merge 1 commit into
ruccho:mainfrom
paq:unified-outline

Conversation

@paq

@paq paq commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

TL;DR

image

Summary

  • Adds an optional unified-outline mode that merges overlapping glyphs into a seamless, non-overlapping mesh.
  • This feature is off by default because, for correctness, each covered font pixel emits an individual quad, which increases mesh-generation cost.

Motivation

Texpix currently generates each glyph independently, which can cause outlines to overlap or create visible seams when glyphs touch or overlap. For example, this happens with negative letter spacing or transparent outlines. These issues prevent the text from appearing as one continuous pixel-art shape.


@ruccho Do you think this feature would be useful? If so, I’d like to work on optimizing it.

@paq
paq marked this pull request as draft August 2, 2026 23:30
@ruccho

ruccho commented Aug 4, 2026

Copy link
Copy Markdown
Owner

@paq
It looks like a very nice feature, but it seems difficult to implement efficiently. While there is likely some room to mitigate the increase in vertex count (mainly uGUI batch creation and GPU cost), I am torn on whether we should accept the cost of scanning the atlas on the CPU, even if it is opt-in.
My alternatives at this point are as follows, none of which are perfect.

A: Outline rendering order

  • A1: Render in two passes for the outline and the body
    • cons: Increased cost due to the extra pass, increased complexity of custom shader implementation
  • A2: Embed adjacent character UVs into vertices and sample the atlas multiple times in the shader
    • cons: Increased fragment shader load, requires Additional Shader Channels setup, increased complexity of custom shader implementation

B: Translucent overlap

This might be an inevitable issue as long as the mesh overlaps within a single pass.

  • B1: Generate vertices in advance on the CPU to avoid mesh overlap (as already implemented)
    • cons: Atlas scanning cost, compatibility with text animations, etc.
  • B2: Separate the mesh parts that could overlap based on metrics instead of the atlas, and render with multisampling like A2
    • cons: Compatibility with text animations, etc., increased complexity of custom shader implementation, requires Additional Shader Channels setup
  • B3: Separate even-numbered and odd-numbered characters into different passes and use stencils to prevent them from interfering with each other
    • cons: Increased passes, increased complexity of custom shader implementation. Incurs stencil setup and clearing costs. Do we also need to consider compatibility with masks?

Also, an unavoidable issue when changing the vertex structure is compatibility when external sources additionally manipulate vertex information, such as with text animations. This might be solved by adding an API that allows external systems to retrieve the correspondence between vertices and characters, but it would require additional work on the user side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants