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\$
  • \$\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\$ – Joe Shanahan Jan 27 '14 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 '14 at 0:09
  • \$\begingroup\$ That is the problem then! I've not worked with 3d so I don't know what to suggest. \$\endgroup\$ – Joe Shanahan Jan 27 '14 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 '14 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\$ – Joe Shanahan Jan 27 '14 at 8:35
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\$
  • \$\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 '14 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\$ – Joe Shanahan Jan 26 '14 at 23:37
  • \$\begingroup\$ try without math.round, just plain int casting \$\endgroup\$ – LearnCocos2D Jan 26 '14 at 23:47
  • \$\begingroup\$ Tried it without Math.Round, still has the same issue. \$\endgroup\$ – Zhafur Jan 26 '14 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\$
  • \$\begingroup\$ It's all choppy, if I truncate it. \$\endgroup\$ – Zhafur Jan 27 '14 at 23:29

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.