# Issues upscaling pixel art with SampleState.PointClamp

I'm developing a 2D game, and I'm striving to create a nice blocky low-res appearance for the game, yet allow it to be played at variable resolutions. So, I've researched resolution independency and have a nice system in place to have my game rendered at 640x480 to a RenderTarget2D, and then have the RenderTarget blown up on the back buffer. Anybody that's looked into this knows that by default scaled images will be antialiased, and to disable that, change the SampleState to PointClamp. So, I've done that, but now I'm having this issue where my sprites aren't upscaling properly. Certain pixels are becoming particularly chunky where they shouldn't be, and I'm not sure what the cause of this behavior is, and I haven't been able to find any documentation of anybody else having this issue, can anybody offer any insight?

The last image illustrates the image rendered in game at 2X the original size. A 2:1 ratio should be a pretty straightforward scale to render, but if you look closely, there are some pixels that are at half size the others.

Edit #2: Here's some code regarding the scaling.

First, the game is captured by the render target at 640x480 resolution, then it is drawn at the back buffer's resolution (in the second image, reslution is 800x600, in the third image, resolution is 1280x960, I haven't messed with alternate aspect ratios yet).

graphicsDevice.SetRenderTarget(RenderTarget);
spriteBatch.Begin();
spriteBatch.Draw(Texture,
new Rectangle((int)location.X, (int)location.Y, frameWidth, frameHeight),
new Rectangle((int)spriteLocation.X, (int)spriteLocation.Y, spriteWidth, spriteHeight,
Color.White,
0f,
Vector2.Zero,
effect,
.826f);
spriteBatch.End();
graphicsDevice.SetRenderTarget(null);
spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null);
spriteBatch.Draw(RenderTarget, new Rectangle(0,0, backbufferWidth, backbufferHeight), Color.White);
spriteBatch.End();


Edit #3: Code involving the sprite's height and width. First, in the class that my monster inherits from, is this little method that runs in the base class' Update() method. It just makes sure that if I have animations with non-uniform sizes, that the sizes are updating properly.

protected void UpdateFrameSizes()
{
frameWidth = animations[currentAnimation].Frames[animations[currentAnimation].currentFrame].SizeAndsource.Width;
frameHeight = animations[currentAnimation].Frames[animations[currentAnimation].currentFrame].SizeAndsource.Height;
}


Then, just to make sure that the Width and Height were correct in his animation class, I checked those:

idleFrame1 = new AnimationFrame(Texture, new Rectangle(154 * 0, 107 * 0, 154, 107), 1f);
idleFrame2 = new AnimationFrame(Texture, new Rectangle(154 * 1, 107 * 0, 154, 107), 1f);
idleFrame3 = new AnimationFrame(Texture, new Rectangle(154 * 2, 107 * 0, 154, 107), 1f);


All looks correct here, I even went to the source image and counted the pixels (Yes, I know, his sprite sheet's dimensions are weird, but they're accurate).

And then this data is all used in Edit #2's code snippet during the draw method.

• You'll probably have to give a code sample of how your up-scaling and point out what the problem is in your image (I can't see it). – MichaelHouse Apr 25 '13 at 20:28
• I think its the artifacts caused by rounding such as the outline causing squares on the shoulder. – ClassicThunder Apr 25 '13 at 20:43
• Added code snippets – TheBroodian Apr 25 '13 at 20:58
• If you scale the first image by 200% and compare it to the third image, you can see that they differ in size. That means you are not scaling to 2x the size correctly. – msell Apr 26 '13 at 5:11
• @msell Thank you, I hadn't realized that on my own. – TheBroodian Apr 26 '13 at 17:20

## 1 Answer

You have to upscale in whole numbers to get the effect you are expecting.

You are scaling it by about 1.8 so dividing the second image by 0.55 would get you the pixel you are sampling. Below is approximately how the sampling is being handled in the example you provided.

1 = 0.55 = 1
2 = 1.1  = 1
3 = 1.65 = 2
4 = 2.2  = 2
5 = 2.75 = 3
6 = 3.3  = 3
7 = 3.85 = 4
8 = 4.4  = 4
9 = 4.95 = 5  <-- This is what is causing your artifact (It can work both ways causing a jump or repeating a pixel more often than is nommal)
10 = 5.5 = 6


Because you are not scaling by a while number you are going to sample inconsistently because the rounding is going to jump in a constant rotation dictated by the ration of the remainder.

In general sprites don't scale very well. If aesthetics are important to you you might want to draw all of the sizes a sprite can be.

• Here's the problem though- even if I scale the game to 2x the size of the rendertarget, the issue persists. At a flat 2x size, the sprites should just be 2x their normal size, but they aren't for some reason. I'll post a picture to illustrate. – TheBroodian Apr 25 '13 at 20:43
• Please do with writing the image using the Texture2D save functionality and include your rendering code too please. – ClassicThunder Apr 25 '13 at 20:45
• The same thing can be caused for the exact the same reasons by having the texture be drawn using non whole numbers when specifying screen coordinates. – ClassicThunder Apr 25 '13 at 20:46
• Added the code to the original question. – TheBroodian Apr 25 '13 at 20:58
• As mentioned you are not using a whole number. – ClassicThunder Apr 25 '13 at 21:04