I'm making a tile-based game, using one spritesheet containing all tile graphics.

Each tile has a size of 32x32 pixels.

The main problem is: when I draw the tile to the screen, if the tile position x and y are not rounded or if scale is activated in spriteBatch.Draw() method (scale != 1.0f), I get some lines of adjacent tiles on the spritesheet into the current tile drawed.

I already tried setting SamplerState to PointClamp, removing AntiAlias, but still doesn't work.

Here I'll show images of some tests that I made, with a test sprite sheet that I've created (I made a 9x9 spritesheet, with each sprite of size 32x32 containing a unique solid color).



SpriteSheet used:

SpriteSheet used

Already tried to remove anti-alias, set PointClamp as sampler state, but still getting this issue, XNA keeps drawing part of the adjacent pixels of the texture on the screen.

What I want is to get the correct area of the tilesheet texture (as seen in the first test, that gets just the yellow pixels).

My question is: Is there any way that I can fix this, WITHOUT adding tile spacing or any other modification involving the tilesheet?

Maybe disabling a texture filtering that is done by XNA, or something like that.

  • \$\begingroup\$ I've tested this on another machine, and it worked normally, as expected. This behavior only happens when I try to execute the game on my virtual machine, don't know why, it seems that the sampler state do not change to PointClamp, or any other one, remaining as LinearClamp. I've tried to change the SamplerState using GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp and got the same result. Tried to use a power of two texture, and didn't worked also. It should be something with the virtual machine, somehow I cannot change the sampler state there. \$\endgroup\$ – user24092 Dec 18 '12 at 4:05
  • \$\begingroup\$ Oh, and forgot to mention, I'm using Reach Game Profile, cause I'm not able to run in HiDef profile on my virtual machine. \$\endgroup\$ – user24092 Dec 18 '12 at 4:15
  • 2
    \$\begingroup\$ If you were able to isolate it to a specific hardware (in this case, a virtual one), and you managed it to run correctly on other hardware, it is very likely that it's a problem with the hardware drivers. Virtual machine graphic adapters are not very featured and may not implement everything correctly. What VM are you using, and with which settings? \$\endgroup\$ – Panda Pajama Dec 18 '12 at 4:37
  • \$\begingroup\$ I'm using VMWare Fusion 5.0.2, running a 64-bit Windows 7 vm on a Mac OS X 10.7.5. Also Accelerate 3D graphics options is enabled, supporting DirectX 9.0EX with Aero and OpenGL 2.1. \$\endgroup\$ – user24092 Dec 18 '12 at 5:01

From my experience, this seems like you aren't setting your SamplerState to PointClamp correctly. This is indicated by the "blending" at the top left corner. Have you tried rendering on different hardware?

First, Your texture isn't a power-of-two Although some wouldn't agree, I always use textures^2. On some older hardware it was a requirement. I would suggesting sizing up to 128x128 (4*32, 4*32)

Second, have you tried setting GraphicsDevice.SamplerState[0] directly? (source)

| improve this answer | |
  • \$\begingroup\$ Forgot to mention, this isn't really a "half-pixel" problem. Unlike mine \$\endgroup\$ – Nathan Goings Dec 18 '12 at 1:25
  • \$\begingroup\$ Thanks for your reply and that link, it seems that I'm having the same problem in here. I was running the game on my virtual machine. I've tried to use a power-of-two texture and tried to set the GraphicsDevice.SamplerState[0] directly, none have worked. \$\endgroup\$ – user24092 Dec 18 '12 at 4:08
  • \$\begingroup\$ I've tested on another machine, and it worked properly. It seems to be a problem with virtual machine drivers. The guy on that link was running the game on a virtual machine too. \$\endgroup\$ – user24092 Dec 18 '12 at 4:36
  • 1
    \$\begingroup\$ Setting a power of two is not necessary in XNA. \$\endgroup\$ – ashes999 Jan 17 '13 at 12:47
  • \$\begingroup\$ @ashes999 No it is not necessary, but on some cards, it does help performance. In some extreme cases, it's required by the card. \$\endgroup\$ – Nathan Goings Jan 17 '13 at 23:02

Based on the images you're showing, it is very clear that the renderer is interpolating, so you have to disable this interpolation. This has little to do with half pixels.

Now, I'm not really knowledgeable in XNA, but a quick google of "xna nearest neighbor interpolation" shows that there are at least two places you can try to disable interpolation:

This one suggests using PointClamp as a parameter for SpriteBatch.Begin(), while this other one suggests setting it at GraphicsDevice.SamplerStates.

You mention you tried setting the sampler state to PointClamp, so how about trying at SpriteBatch.Begin()?

| improve this answer | |
  • \$\begingroup\$ Thank you, I've corrected the post title. With SpriteBatch.Begin() with no arguments, the SamplerState used is set to SamplerState.LinearClamp. But I've tried it anyway, and didn't worked. \$\endgroup\$ – user24092 Dec 18 '12 at 4:17

I had exactly the same problem that User24092, and I tried all those suggestions with no result. Finally the solution suggested by Panda Pajama made the trick!

Just set the PointClamp sampler state when you begin the spriteBatch:

spriteBatch.Begin(SpriteSortMode.Immediate, null, SamplerState.PointClamp, null,null);

It worked like a charm!

| improve this answer | |

The best way to fix this is to round your X and Y values before drawing them.

The "usual" way I handle this in XNA is to keep X and Y internally as a float, and to expose them externally (eg. to SpriteBatch) as an int. You should, of course, use Math.Floor to get you the correct tile.

The code would look something like this:

float x, y = 0f;
// ...
public int X { get { return (int)Math.Floor(this.x); } }
public int Y { get { return (int)Math.Floor(this.y); } }
spriteBatch.Draw(this.texture, new Vector2(this.X, this.Y), Color.White);
| improve this answer | |
  • \$\begingroup\$ I've already tried this, there is just a problem, I want to do scaling too, and with scale even if the sprite location is setted with Math.Floor, this strange behavior ocurrs. Maybe I should calculate the size of the sprite after the scale applying a Vector2.Tranform and remove it from the location calculated? I'm gonna try this, btw, thanks for your reply. \$\endgroup\$ – user24092 Dec 18 '12 at 4:12
  • \$\begingroup\$ Use the overload for Draw that takes in a source rectangle, and pass in the proper coordinates. That should solve the problem; scaling shouldn't matter then. \$\endgroup\$ – ashes999 Dec 18 '12 at 12:40
  • \$\begingroup\$ I'm already using the approach that takes in a source rectangle. Do you mean destination rectangle? I tried using destination rectangle, instead of using scale, and scaling it by setting the width and height of the rectangle, which are Integers, but still having that interpolation problem. \$\endgroup\$ – user24092 Dec 19 '12 at 5:16
  • \$\begingroup\$ No, I meant a source rectangle, not a destination rectangle. \$\endgroup\$ – ashes999 Dec 19 '12 at 12:11
  • \$\begingroup\$ Can you try creating a new project and using a different spritesheet image? That'll isolate if it's related to something else in your project or not. \$\endgroup\$ – ashes999 Jan 17 '13 at 12:49

I know it may be a bit extreme, but try to apply a pixel shader with filter point to force that the exact pixels are rendered. I'm really curious with this problem.

Texture Sprite;
sampler SamplerSprite = sampler_state {
    texture = <Sprite>;
    filter = POINT;

float4 Ps_Main(float2 coord : TEXCOORD0) : COLOR {
    return tex2D(SamplerSprite, coord);

technique Tech_0 {
    pass Pass_0 {
            pixelshader = compile ps_2_0 Ps_Main();
| improve this answer | |
  • \$\begingroup\$ Yeah, I've tried this already! I thought the same, haha, it's kind of extreme but.. let's try it out! But the result is: it still keeps interpolating ): \$\endgroup\$ – user24092 Dec 19 '12 at 5:19

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.