I am making a small RPG game and I'm currently on window rendering (things like inventory/quest windows).
I draw the actual window with 9 quads textured from a "skin", 4 corners, 4 borders and the middle.
The problem is, at arbitrary coordinates a triangle or two shifts slightly downwards. It happens consistently, and only if PointClamp or PointWrap is used. Other opions work fine but they give a blurry look.
The same bug actually happens with the green bar above, however I "fixed" it by using Linear instead of Point.
I use this function to convert from pixel coordinates to screen coordinates:
Note: This function works as I originally expected in MonoGame.
public static Vector3 PixelToScreen(GraphicsDevice device, float X, float Y)
{
float xscale = (float)device.Viewport.Width / 2;
float yscale = (float)device.Viewport.Height / 2;
return new Vector3(((int)X / xscale) - 1f, 1f - ((int)Y / yscale), 0);
}
I suspect this function might be the source of my problem. Is there a "right way" to do it?
A picture is worth a thousand words, so here's a screenshot with the problem.
https://i.sstatic.net/rNsnH.png
I am quite sure the solution is trivial, but I just can't catch it.
UPDATE
After some more digging and researching, I finally found a solution. It turns out that it has something to do with how texture pixels are mapped to the screen pixels.
UPDATE #2
After porting this code to MonoGame, I've noticed a different bug where everything looks "blurry". Curiously enough, removing the offset (reverting to the original function) fixes the problem!
public static Vector3 PixelToScreen(GraphicsDevice device, float X, float Y)
{
X -= 0.5f; // Offset the "pixel value" by half a pixel
Y -= 0.5f; // To provide "expected results" use negative value
float xscale = (float)device.Viewport.Width / 2;
float yscale = (float)device.Viewport.Height / 2;
return new Vector3((X / xscale) - 1f, 1f - (Y / yscale), 0);
}
Directly Mapping Texels to Pixels (Direct3D 9)
Understanding Half-Pixel and Half-Texel Offsets
This question is obviously resolved now, but I hope my findings will help someone stuck in the same situation.
public static Vector3 PixelToScreen(GraphicsDevice device, float X, float Y)
{
X -= 0.5f; // Offset the "pixel value" by half a pixel
Y -= 0.5f; // To provide "expected results" use negative value
float xscale = (float)device.Viewport.Width / 2;
float yscale = (float)device.Viewport.Height / 2;
return new Vector3((X / xscale) - 1f, 1f - (Y / yscale), 0);
}
Do not use these offsets in MonoGame as it somehow takes care of the matters internally.