I’ve seen this quite a bit around on XNA forums and got 2 emails last week asking about this:
I want to make a 3000×3000 grass background by tiling this small grass image I have. Should I make one big image or should I make a for cycle drawing the image (3000/TileSize) times?
My answer is neither of them. The big image has a huge impact on every Draw and more, you are limiting your map to the max Texture Size the graphic card can handle.
The drawing lots of small images can actually work, if they are few. Let’s say your small texture size is 64×64. That means in order to fill up the 3000×3000 you have to draw it (3000/64) = 47 times. Since it’s a 3000×3000 that sums to (47×47) = 2209 Draws. Just for a background. Not to mention the rest of the actual game 😛
What if you could do this in just one Draw()?
It’s very very easy to achieve this effect by setting TextureAddressMode to Wrap. Basically giving it a bigger Rectangle but telling to wrap the texture so you are gonna get tiles =)
spriteBatch.Begin(SpriteBlendMode.AlphaBlend,SpriteSortMode.Immediate,SaveStateMode.None); GraphicsDevice.SamplerStates[0].AddressU = TextureAddressMode.Wrap; GraphicsDevice.SamplerStates[0].AddressV = TextureAddressMode.Wrap; |
Next we draw a texture with a big source rectangle
Rectangle source = new Rectangle(0, 0, 400, 200); spriteBatch.Draw(texture, Vector2.Zero, source, Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f); |
So instead of this:
You end up with this:
On a small test I made, using a 30000×30000 Rectangle I got a frame drop to 35 FPS by doing tons of regular Draws, when switching to Wrap mode a solid 60 FPS.
As I told you it’s very easy. I’ll write more advance tutorial one of this days on how to achieve cool effect like mixing two textures with a noise/normal map.
You can play with this sample by downloading it here.
Great article. I didin’t knew that and it sure would help a lot of people in their games.
thanks
GREAT POST! Already started to use this on my games! Thanks a lot!
Interesting.
But it would be better to draw only the visible brackground?
Yes. But you can still split into draw several background tiles and only drawing the visible ones. But instead oh having 300 tiles you can have like 4 ou 5
I’ve been looking for tutorial like this, thank you very much, but the sample didn’t compile after conversion with VS 2010/XNA 4, errors complained about SaveStateMode and SpriteBlendMode.
Could you please update the code/upload newer sample?
In VS 2010 is something like
In VS 2010, XNA 4.0
I’m getting the “Create new Samplerstate instance error after using Bradpako’s code, how do I Create a new SamplerState?
You should not use the code:
GraphicsDevice.SamplerStates[0].AddressU = TextureAddressMode.Wrap;
GraphicsDevice.SamplerStates[0].AddressV = TextureAddressMode.Wrap;
This is read only. No need to use it for me.
It’s a shame this is outdated.
I get errors for
spriteBatch.Begin(SpriteBlendMode.AlphaBlend,SpriteSortMode.Immediate,SaveStateMode.None);
and
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend,
SamplerState.PointWrap,
null,
null,
null,
null);
What errors are you getting? Also which XNA version are you using? it should work on 4 with that last code
XNA 4.0
—CODE
spriteBatch.Begin(SpriteBlendMode.AlphaBlend,SpriteSortMode.Immediate,SaveStateMode.None);
—ERRORS
“The name ‘SaveStateMode’ does not exist in the current context.”
“The name ‘SpriteBlendMode’ does not exist in the current context.”
—CODE
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend,
SamplerState.PointWrap,
null,
null,
null,
null);
—ERRORS
“Argument 7: cannot convert from ” to ‘Microsoft.Xna.Framework.Matrix'”
You’d think that spriteBatch.Draw would provide a tile argument such as;
spriteBatch.Draw(texture, rectangle, Color.Blue, windowWidth, windowHeight);
where it would fit the texture into the rectangle, and then tile that rectangle inside the imaginary rectangle made by windowWidth and windowHeight.
Correction: In the errors for the second code, it’s “Argument 7: cannot convert from ” to ‘Microsoft.Xna.Framework.Matrix'”
Okay the ” are being registered as HTML and it’s removing ‘null’ after ‘cannot convert from’
Sorry about that!
I’d edit the comments if I could.
Basically, the arrow brackets are making parts of the text disappear from my replies.
try sending a identity matrix to see if it builds then. Maybe the latest xna updates don’t accept null anymore
convert from ” to ‘Microsoft.Xna.Framework.Matrix’” is a weird error, it doesn’t say what type it’s failing from to convert. I have no idea what the problem may be. That code usually works
Matrix.Identity removed the errors, but there’s no tiling going on.
I’ve tried the simple method of drawing the texture for each Vector2 in a list, which is terrible and drops the frame rate.
I’ve looked everywhere for tiling methods in XNA.
They either don’t work or mention this post by you which unfortunately isn’t working for me.
works fine in 2012 gs 4,0.
SamplerState state = new SamplerState();
state.AddressU = TextureAddressMode.Wrap;
state.AddressV = TextureAddressMode.Wrap;
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, state, null, null);
or alternately
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointWrap, null, null);
works fine too