1
\$\begingroup\$

So I'm working on a project and started working on a scaling system for different resolutions.

I know if you change the monogame resolutions, that the texture won't scale but I noticed deformed pixels. I just changed the PreferredBackBufferWidth to 1920 and the PreferredBackBufferHeight to 1080 but my pixels are deformed.I did some research and tested some resolutions and the only ones that don't work are 1920x1080 and higher.(1920x1080 works in fullscreen)

Draw method for sprites:

public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch, Color color)
{
    spriteBatch.Draw(textureImage, position, new Rectangle(
    (currentFrame.X * frameSize.X),
    (currentFrame.Y * frameSize.Y),
    frameSize.X, frameSize.Y),
    color, 0, Vector2.Zero, 1, SpriteEffects.None, 0);
}

spriteBatch.Begin:

spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullCounterClockwise, null);

enter image description here enter image description here

The first picture is the player head with the new resolution (without scaling the textures!) and the second picture is the player head with the default resolution (you can't see all the pixels at the bottom).

You can see that in the first picture a few pixels are deformed.

Question: Why doesn't 1920x1080 work in windowed mode (it works in fullscreen though) without deformation (I use a 1920x1080 monitor)? All I do is just enlarging the game window, I'm not scaling sprites...

-> is this because I have a 1920x1080 monitor?

\$\endgroup\$
  • \$\begingroup\$ Need more information about how exactly your are drawing this sprite. Specifically, what is the exact Draw() call you are making? \$\endgroup\$ – JonBee Dec 31 '15 at 18:29
  • \$\begingroup\$ @JonBee The question is edited. But I don't think it's a draw method problem, because it works with the default monogame resolution. \$\endgroup\$ – Jelle Dec 31 '15 at 18:47
  • \$\begingroup\$ Alrighty; Is scaleSize set to 1.0f? And do you call ApplyChanges() after setting backbuffer dimensions? \$\endgroup\$ – JonBee Dec 31 '15 at 19:01
  • \$\begingroup\$ @JonBee My project is compactible with both scaleSize 1 and 2 (I can switch between the two), and there's no pixel deformation for both 1 and 2 for the default resolution. There's deformation when the resolution is 1920x1080 with both scaleSize 1 and 2. And yes, I call Graphics.ApplyChanges(); after setting the backbuffer dimensions. (Graphics is my GraphicsDeviceManager.) EDIT: I found out that there's also no deformation for 1920x1000 (no resolution for a pc) but this means that the deformation only occurs for certain resolutions. \$\endgroup\$ – Jelle Dec 31 '15 at 22:54
  • \$\begingroup\$ EDIT: ScaleSize is removed (always 1 now), but the textures are just drawn 2x bigger. \$\endgroup\$ – Jelle Jan 3 '16 at 20:28
2
\$\begingroup\$

-> is this because I have a 1920x1080 monitor?

Yes it is. On a 1920x1080 monitor you can't have a windowed game and also have a 1920x1080 canvas. The window title and edges also take up space. The graphics backbuffer is initialized at 1920x1080 but the internal windows logic scales the canvas to fit inside the window, causing the scaling artifacts. In windowed mode Windows also handles the graphics viewport so it knows where the window is on the desktop, this is a result of that.

You can see this by 'hiding' the windows border:

Using System.Windows.Forms; //also add reference to system.windows.forms in the project

Form MyGameForm = (Form)Form.FromHandle(Window.Handle);
MyGameForm.FormBorderStyle = FormBorderStyle.None;

It may look like fullscreen but it still is in windowed mode (just without showing the window border). But now the viewport can take up the entire screen and the artefacts are gone.

Note: This is default behaviour since XP/Vista. There may be code out there that overrides this but that is beyond this question.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer. I wasn't sure if the reason you give me now was right (I did think it was because of this). \$\endgroup\$ – Jelle Jan 5 '16 at 16:59
1
\$\begingroup\$

The true cause of the artifacts you are seeing is going to be SamplerState.PointClamp. Due to the way this filtering works, you will see some texels taking up more or less space than neighboring ones as the texture is stretched over it's area.

What's more, is that the texels being deformed will likely change as the sprite or your camera moves about on screen.

There are various fixes for this that you can use, but one that I've recently implemented for a tiny pixel-art type game was to render to a smaller-resolution RenderTarget and then scale it to fit the window. The tricky bit becomes determining the size of your RenderTarget. If you want to keep your sharp edges, it needs to be the size of your screen divided by a round number.

So in your case of 1920x1080, to scale the pixels evenly by a factor of 2, you would create a RenderTarget at 960x540, render your sprites unscaled to that, then draw the RenderTarget to the screen, scaling it times 2.

Image of a scaled RenderTarget

\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer. I use no scaling right now, because I want the game to be pixel perfect on each resolution. So I just enlarge the screen (so smaller resolutions will not see so many as big resolutions). But thanks for the answer regarding pixel scaling. I think I can use this in the future! :) \$\endgroup\$ – Jelle Jan 5 '16 at 17:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.