# Rounded corners in XNA?

Is there any way that I can make rounded corners on a rectangle rendered in XNA through primitives (line-strips)? I want to make my UI a bit more fancy than it is already, and I would like the code to be flexible, without too many textures involved.

• Basically: Use one texture for the line, one texture for the round ends of the line. Rotate and scale sprites that use these two textures appropriately. – Olhovsky Jun 7 '11 at 4:41

You can render your primitive, and make a shader that can create these rounded corners.
Here is a simple pixel shader in pseudocode that can draw a rounded square:

xDist = abs(x-0.5)
yDist = abs(y-0.5)
xD = xDist*xDist*4
yD = yDist*yDist*4
alpha = floor((1-xD)*(1-yD)*5)


If you use shaders, you can make really fancy UI, even an animated one.

For me great to prototype simple pixel shaders is program EvalDraw

Another way to do this is to use a 'button stretch' (also called a 'box stretch' or 'nine-patch'). Essentially you create an image that is made up of 9 parts:

In order to draw that button at any size, you draw each piece (from top to bottom, left to right):

1. Draw unscaled at the top left of the destination rectangle.
2. Draw scaled horizontally (with width - ((1) + (2)).Width) at the top of the destination rectangle, with the left offset by the width of (1).
3. Draw unscaled at the top right of the destination rectangle.
4. Draw scaled vertically (with height - ((1) + (2)).Height) at the left of the destination rectangle, with the top offset by the height of (1).
5. Draw scaled in both directions (with the width of (2) and height of (4)), offset by the width and height of (1).
6. Draw scaled vertically (same height as (4)) at the right of destination rectangle, offset by the height of (1).
7. Draw unscaled at the bottom left of the destination rectangle.
8. Draw scaled horizontally (same height as (2)) at the bottom of the destination rectangle, offset by the width of (1).
9. Draw unscaled at the bottom right of the destination rectangle.

If you look at the button you will see that it doesn't matter if (2), (5) and (7) get scaled horizontally (because it is essentially a straight line); in the same manner (4), (5) and (6) can be scaled vertically without affecting the quality of the image.

• Yes, this doesn't answer the question directly - but someone might still find it useful. – Jonathan Dickinson Nov 15 '11 at 13:27
• It's called a nine-patch and is actually much more flexible (and cheaper!) than using a shader since you can make it look however you want with a texture. You can then put all your widget images in a single texture atlas. Most GUIs do it this way. – Elisée Nov 16 '11 at 12:27

Here is the code for the "nine-patch" approach:

public static class SpriteBatchExtensions
{
public static void DrawRoundedRect(this SpriteBatch spriteBatch, Rectangle destinationRectangle,
Texture2D texture, int border, Color color)
{
// Top left
spriteBatch.Draw(
texture,
new Rectangle(destinationRectangle.Location, new Point(border)),
new Rectangle(0, 0, border, border),
color);

// Top
spriteBatch.Draw(
texture,
new Rectangle(destinationRectangle.Location + new Point(border, 0),
new Point(destinationRectangle.Width - border * 2, border)),
new Rectangle(border, 0, texture.Width - border * 2, border),
color);

// Top right
spriteBatch.Draw(
texture,
new Rectangle(destinationRectangle.Location + new Point(destinationRectangle.Width - border, 0), new Point(border)),
new Rectangle(texture.Width - border, 0, border, border),
color);

// Middle left
spriteBatch.Draw(
texture,
new Rectangle(destinationRectangle.Location + new Point(0, border), new Point(border, destinationRectangle.Height - border * 2)),
new Rectangle(0, border, border, texture.Height - border * 2),
color);

// Middle
spriteBatch.Draw(
texture,
new Rectangle(destinationRectangle.Location + new Point(border), destinationRectangle.Size - new Point(border * 2)),
new Rectangle(border, border, texture.Width - border * 2, texture.Height - border * 2),
color);

// Middle right
spriteBatch.Draw(
texture,
new Rectangle(destinationRectangle.Location + new Point(destinationRectangle.Width - border, border),
new Point(border, destinationRectangle.Height - border * 2)),
new Rectangle(texture.Width - border, border, border, texture.Height - border * 2),
color);

// Bottom left
spriteBatch.Draw(
texture,
new Rectangle(destinationRectangle.Location + new Point(0, destinationRectangle.Height - border), new Point(border)),
new Rectangle(0, texture.Height - border, border, border),
color);

// Bottom
spriteBatch.Draw(
texture,
new Rectangle(destinationRectangle.Location + new Point(border, destinationRectangle.Height - border),
new Point(destinationRectangle.Width - border * 2, border)),
new Rectangle(border, texture.Height - border, texture.Width - border * 2, border),
color);

// Bottom right
spriteBatch.Draw(
texture,
new Rectangle(destinationRectangle.Location + destinationRectangle.Size - new Point(border), new Point(border)),
new Rectangle(texture.Width - border, texture.Height - border, border, border),
color);
}
}


It is invoked as:

spriteBatch.DrawRoundedRect(
dest, // The coordinates of the Rectangle to be drawn
rectangleTexture, // Texture for the whole rounded rectangle
16, // Distance from the edges of the texture to the "middle" patch
Color.OrangeRed);

• this does not work for me... I just get a normal rectangle. This is how I used it Texture2D _texture = new Texture2D(GraphicsDevice, 1, 1); _texture.SetData(new Color[] { Color.Blue }); SpriteBatch sb = new SpriteBatch(GraphicsDevice); sb.Begin(); //sb.Draw(_texture, new Rectangle(100, 100, 100, 100), Color.White); sb.DrawRoundedRect(_texture, new Rectangle(100, 100, 100, 100), Color.Pink, 16); sb.End(); – Leonardo Seccia Feb 1 '18 at 17:31
• Your texture is just one blue pixel, this approach assumes the rounded corners are part of your texture. – sdgfsdh Feb 1 '18 at 17:35
• sorry - very new to platform... thanks for getting back to me so quickly – Leonardo Seccia Feb 1 '18 at 17:38