I'm trying to plot squares using MetalKit. Each square has an origin and a size, like this:
Origin:
▿ (204.5746214852199, 62.83450704225352)
- x : 204.5746214852199
- y : 62.83450704225352
Size:
▿ (1.4612472963229992, 1.4612676056338028)
- width : 1.4612472963229992
- height : 1.4612676056338028
The problem is that when MetalKit draws those, each square is drawn a different weird way that exceeds the expected area and shape for what a square should look like (see image below) - yes, each red cluster should represent a single 1x1 square of the same size of those grey squares underneath. Furthermore, its borders are also blurry (this is a zoomed in image). I am using this sampler:
constexpr sampler textureSampler(mag_filter::nearest,
min_filter::nearest);
In the image above, the greyscale squares is what each red square should be fitting to (their borders and exact position).
Any clue how to achieve this? Could MetalKit be losing decimal precision along the way? How can I make the squares edges sharp?
Here's my vertices function and position struct: https://github.com/s1ddok/MetalCoreGraphics/blob/d32c680a156548e20e9e9deb06e14cc260bcdea1/MetalCoreGraphics/Shaders.metal#L12-L30
Any leads would be super helpful here! Appreciate it!
I was able to figure things out in the end. It was a combination of several things.
CGContext
to bridge between CPU and GPU memory (strategy taken from here), I had to add the following code (both lines!):context.setShouldAntialias(false)
context.setAllowsAntialiasing(false)
layer.magnificationFilter = .nearest // Disables pixel interpolation when zooming in
CGRects
(context.addRects()
), and those CGRects had a too-precise width/height, often smaller than 1.00 (even though that wasn't the case in the original question, it had floating points which isn't really a thing when drawing individual pixels - there's no such thing as half of a pixel). So the solution to this was to use a canvas that has the exact number of pixels needed, and have all the CGRects I'm drawing to have a 1x1pt size. This way it's not only more performant (since there won't be floating point calculations all the time), but it will always be pixel perfect.See the final result below (this view is zoomed in by 150 times using UIScrollView
):
Hope this helps somebody out there! Thanks everyone who contributed!