Optimised SDF generation #224
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The implementation is based on A Fast Algorithm for Computing the Closest Point and Distance Transform by Sean Mauch. That paper's available here https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=c4b3fe3775c2d718b1face6a1f65e7707ee99e03, although I don't know how likely that link is to still be alive when future generations look at this PR.
The gist of the algorithm is that instead of computing the distance for every texel from every line segment and choosing the minimum, it considers only the region around each line segment and vertex that could be closer to that element than its neighbours are, and does everything in an order that makes the bounds checking amenable to polygon scanline conversion (as it's about as fast to rasterise a whole line as it is to check whether a single point is within a polygon).
When running with a profiler taking four thousand samples per second, the original implementation took 6800-8000 samples for Arial, so 1.7-2 seconds, whereas this implementation takes 2300-2500 samples, so around 0.6 seconds, which is less than a third as long. That should be a significant enough improvement that a lot of apps will be able to tolerate loading fonts from scratch on launch which would have needed to preconvert fonts to
.vsgbotherwise.I've mostly tested Arial, and the SDF that's output is nearly identical. A small number of texels have a value that's different by one, which is explainable as rounding error given that the maths is done as 32-bit floats and then the results are converted to SNORM16. It shouldn't result in a visible difference when the SDF is sampled. (Note that text has some pretty bad artefacts under some conditions with or without this PR, which has been reported as vsg-dev/VulkanSceneGraph#1311. From my testing, it appears to be because atlas tiles aren't big enough for the SDF values to get to zero before the edges are cropped, and if we fixed it by making the tiles bigger, this PR would become even more useful as each SDF texel is cheaper to generate).