Unable to draw a sprite properly from a spritesheet

I have a spritesheet with 2 sprites. Each sprite is 40x60. The total size of the image is 40x120. It looks like this (the red line is part of the 1st sprite). I’ll tell you in a second why I added that.

It seems that for some reason, when trying to draw the second sprite, it will always take the last line of the previous sprite. I have drawn that red line to illustrate that.

This is my code that draws the 2nd sprite:

Rectangle rect = new Rectangle(0, 60, 40, 60); // Choose 2nd sprite
Vector2 pos = new Vector2(100, 100);
Vector2 origin = new Vector2(0, 0);

spriteBatch.Begin();
spriteBatch.Draw(mSpriteTexture, pos , rect, Color.White, 0.0f, origin, 6, SpriteEffects.None, 0.0f);
spriteBatch.End();

And this is how it looks when I run the program:

Any ideas what I’m doing wrong?

Note: For this example I’m using scale=6. I did this because it seems that when scale > 1 this problem will always happen. If scale = 1, it doesn’t seem to happen all the time.

I had same thing and resolved it by adding some empty space between sprites in spritesheet and set SamplerState.PointClamp in spritebatch.Draw. Maybe it’s not proper way to do that but it should work…

Spritesheet 40x122 .
Rectangle rect1 = new Rectangle(0, 60, 40, 60);
Rectangle rect2 = new Rectangle(0, 62, 40, 60);

1 Like

Ain’t it a problem when passing from pixels coordinates in the spritesheet to texture coordinates (0-1 or -1 - 1) with rounding errors?

1 Like

Using SamplerState.PointClamp made a difference. It works now but when scale > 1.
If scale == 1, it will still happen from time to time.

I’ve spent a whole day on this, I don’t know what else to do… I wish somebody can give me another hint. So close…

Try putting some spacing between the frames, just one pixel should do the trick.

1 Like

yeah, I will have to do that. Thanks. :slight_smile:

1 Like

One pixel is not enough.

Yes its a floating point rounding error gpu’s do sampling from nearby pixels so setting point clamp means sample the point and clamp the edges of the texture clamp part doesn’t matter though.

Even still you can still get rounding errors and in some cases they can be 2 pixels wide.

This is because…

The projection matrix multiplies it down to a ranged value of -1 to 1 however the value that is multiplying it is dependant upon the screen width and height which my vary.

So its a double rounding error with sampling or even triple.

You can see this for yourself by simply running in windowed mode and turn on AllowUserResizing = true in your game constructor then slowly resizing your screen up and down by small amounts. The red line will disappear now and then and if you look closely.
You will also see that you might lose a line from time to time.

Id recommend also that you do not scale it via the parameter use a scaled drawing rectangle as the destination. (though it wont stop the above behavior which you have no control over) You can purposely overdraw the destination from up to down or down to up to try to cover it up. Or in your source rectangle - 1 off the Height and add 1 to Y.

spriteBatch.Draw(texture, screenDrawTect, sourceTexelRect, Color.White, 0.0f, Vector2.Zero, SpriteEffects.None, 0.0f);

also

separate the textures by 2 or 3 pixels of transparent color or color 0,0,0,0 if premultiplied alpha is turned off.

The only real way around it at the moment is to actually draw them directly yourself via drawuserprimitives and add a fractional value of about 1 / (screenHeight -1) to the Y position or some small value. It will happen for the x value as well.

It’s a problem carried over from xna.

I made a petition for a full spriteBatch draw overload that takes floats for everything and even vertex and uv vertex coordinates but i guess it wasn’t meet with much enthusiasm.

1 Like

willmotil,

Thanks for your detailed answer and your help. You provided some good options to try there.
And you are right, one pixel was not enough. I had to add 2 lines and then the problem didn’t happen.

I will continue developing my game using your hints, especially the one about not scaling. Thanks again!