Skip to content

Conversation

@AnyOldName3
Copy link
Contributor

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 .vsgb otherwise.

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).

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.
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.

1 participant