Open
Conversation
The implementation's based on *A Fast Algorithm for Computing the Closest Point and Distance Transform* by Sean Mauch. At the moment, it's slower than the previous implementation as I cut some corners to get something that works. The two key things from this algorithm are that it only computes the distance from edges for texels that might be closest to that edge, and that it does in-polygon tests line-by-line, so it can be done as scanline rasterisation, which can be faster than a from-scratch check for each texel. I've not used scanline rasterisation, which is a big part of why this is slow, and intend to do that in a later commit. Also, I've not profiled to see which bits of my new maths are slow and could be rearranged.
…is within the contours. This is much faster as it takes a similar amount of time to rasterise a whole line as it does to check a single point.
Scan conversion seems more stable, so this tweak no longer accomplishes anything productive.
On some implementations, it's a little faster to zero-fill the scanline upfront.
12 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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).