Apples Metal hello 2D triangle example doesn't appear to be 2D in the way I had hoped.
I was expecting to have 1 on x and 1 on y to be exactly 1 pixel and for it to start at the top left.
I would have thought that 2D implies flat and with no concept of depth it naturally follows to have 1 unit to map to 1 pixel, how can I fix the example to work in the way I expected it to? General concepts of coarse, no need to actually produce the code unless you really like unicorns in which case please do; so I can communicate to the world my brilliance.
https://developer.apple.com/documentation/metal/hello_triangle
static const AAPLVertex triangleVertices[] =
{
// 2D positions, RGBA colors
{ { 0, 0 }, { 1, 0, 0, 1 } },
{ { 0, 4 }, { 0, 1, 0, 1 } },
{ { 4, 0 }, { 0, 0, 1, 1 } },
{ { 4, 4 }, { 0, 1, 0, 1 } },
};
These coordinates as a line strip produces a 4 by 5 px N!
Update
I was unable to resolve/understand why a 4 by 5 px line strip is drawn. I believe the line strip algorithm is incorrect.
Triangle strip with expected result vs Same but line strip with unexpected results
Consider this line strip 3 vertex corner:
static const AAPLVertex triangleVertices[] =
{
// 2D positions, RGBA colors
{ { 0, 4 }, { 1, 0, 0, 1 } },
{ { 0, 0 }, { 0, 1, 0, 1 } },
{ { 4, 0 }, { 0, 0, 1, 1 } },
};
It seems you basically want to specify your initial vertex positions in window coordinates. That will get you the 1:1 pixel-to-unit mapping that you're after.
The job here is to come up with a sequence of transformations that allows you to specify vertices in window space, while honoring the fact that vertex positions returned from your vertex function must be in clip space. The inverse of this transformation is applied during rasterization, so we're trying to cancel it out.
We'll ignore depth. Clip space ranges from -1 to 1 in both X and Y directions. So we want to map the origin of our space (0, 0) to (-1, 1) in clip space. Similarly, we want to map the bottom-right (width, height) of our space to (1, -1) in clip space.
We can get most of the way there by multiplying the pixel coordinates by 2, subtracting the viewport size, and finally dividing by the viewport size. This replaces the computation of the clip space coordinates in the example's vertex function:
out.clipSpacePosition.xy = ((pixelSpacePosition * 2) - viewportSize) / viewportSize;
In this space, Y increases downward, but the Y axis in clip space increases upward, so we need to flip it:
out.clipSpacePosition.y *= -1;