1
\$\begingroup\$

Why does XNA blurs the images which moves less than 1px in between two draws? It is quite annoying, because everything looks really blurry. Is there a way to disable it?

I have tried to set the SamplerState of the spritebatch's SamplerState to PointWrap in it's Begin function, but then it wraps the images to pixels, thus they move choppy. Any suggestions? Thanks!

My SpriteBatch's Begin function:

spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);

Edit:

public class Image:IDisplay
{
    public Texture2D texture;
    private BaseModel model;
    private Vector2 position;
    private Util.DISPLAY_LAYERS layer;
    public Image(String asset, BaseModel _model)
    {
        model = _model;
        texture = Main.current.Content.Load<Texture2D>(asset);
        DisplayManager.add(this, model.layer);
    }
}

This is how the Image class looks like (without additional functions), and this is it's draw function which is being called.

public void Draw(SpriteBatch batch)
    {
        if (model== null)
        {
            batch.Draw(texture, position, Color.White);
        }
        else {
            position.X = (int)Math.Round(model.Position.X, MidpointRounding.AwayFromZero);
            position.Y = (int)Math.Round(model.Position.Y, MidpointRounding.AwayFromZero);
            batch.Draw(texture, position, Color.White);
        }
    }
\$\endgroup\$
6
  • \$\begingroup\$ Are model.Position.X (and Y) representing pixel coordinates or some kind of game world coordinates? Perhaps your model's position is being changed with very small values (value < 1) over time (time > 1sec). \$\endgroup\$ Jan 27, 2014 at 0:06
  • \$\begingroup\$ There are models with coordinates' change by very little, like 0.005f. If I would use integers, then the movement wouldn't been that smooth then. This might cause the problem. \$\endgroup\$
    – Zhafur
    Jan 27, 2014 at 0:09
  • \$\begingroup\$ That is the problem then! I've not worked with 3d so I don't know what to suggest. \$\endgroup\$ Jan 27, 2014 at 1:15
  • \$\begingroup\$ It's 2D, "models" are not 3D models, but ""models"", there are UnitModels, they contain hp, speed, position and stuff like that. I have seperated the View and the Model. en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller \$\endgroup\$
    – Zhafur
    Jan 27, 2014 at 2:03
  • \$\begingroup\$ Then you need to massively increase the scale of your positioning system. Positions should be 0 -> 1000 (roughly) rather than 0 -> 0.01f! A good place to start is +/- 1 unit per frame for movement and adjust from there. \$\endgroup\$ Jan 27, 2014 at 8:35

2 Answers 2

1
\$\begingroup\$

The problem is the renderer is anti-aliasing that sub-1px difference. You can disable this by either setting the sampler state to point clamp in your SpriteBatch.Begin call like so:

sb.Begin(
    SpriteSortMode.Deferred, 
    BlendState.AlphaBlend, 
    SamplerState.PointClamp, // <------
    DepthStencilState.None, 
    RasterizerState.CullCounterClockwise, 
    null, 
    Matrix.Indentity);

However anti-aliasing is beneficial for rotated and non-integer scaled objects. My suggestion would be to not have floating point drawing positions.

So that you don't have to refactor your positions to int, I would suggest you either cast your coordinates to int in the drawing method, or for better accuracy (for a marginal performance hit), round them and then cast to int like so:

    spirteBatch.Draw(
        _texture, 
        new Vector2(
            (int)Math.Round(posX, MidpointRounding.AwayFromZero),  // <------
            (int)Math.Round(posY, MidpointRounding.AwayFromZero)), // <------
        null,
        _drawColor, 
        _rotation, 
        new Vector2(_texture.Width / 2, _texture.Height / 2),
        _scale,
        SpriteEffects.None, 
        0
    );

It's probably better to get in to the habit of having _drawX/_drawY as fields defined outside of a method so that you can calculate the draw coordinates within an Update() method. This is better because if you were ever trying to find a bottleneck or bad code, having all your logic being done from one method makes it easier to track it down.

\$\endgroup\$
4
  • \$\begingroup\$ Thank you for your answer, I've tried the second method you suggested, but now it looks choppy, it's like an FPS drop to 3fps. \$\endgroup\$
    – Zhafur
    Jan 26, 2014 at 23:18
  • \$\begingroup\$ That shouldn't be happening. Please will you edit your question to include how you store and set your object's position and how you trying to draw it. \$\endgroup\$ Jan 26, 2014 at 23:37
  • \$\begingroup\$ try without math.round, just plain int casting \$\endgroup\$
    – CodeSmile
    Jan 26, 2014 at 23:47
  • \$\begingroup\$ Tried it without Math.Round, still has the same issue. \$\endgroup\$
    – Zhafur
    Jan 26, 2014 at 23:58
0
\$\begingroup\$

You can truncate/round the float coords of the position of the sprites into int (only do this during the Draw() method). This will avoid the blurred effect, since the graphics card will not need to deal with "broken" coords.

\$\endgroup\$
1
  • \$\begingroup\$ It's all choppy, if I truncate it. \$\endgroup\$
    – Zhafur
    Jan 27, 2014 at 23:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .