# What can I do to render generated 2D terrain in XNA?

I am working on a smooth terrain generation algorithm in C# and using XNA to display the data.

I am making it so it creates a new point halfway between each point per iteration, at a random height between the two. This works OK, and I am getting the current result, randomly placed points.

Now what I want to do is turn these points into a primitive (I think that is what it is) and display it like a mountain, obviously using a mountain texture. Example below (using different point data, made up in paint)

Any help or tips are greatly appreciated, and look forward to your responses.

In addition to Blau's answer you could also generate a VertexBuffer. What you would do is something like:

// Create the arrays to hold the data.
var vertices = new VertexPositionColorTexture[_points.Length * 2];
var indicies = new short[6 * (_points.Length - 1)];

for (var i = 0; i < _points.Length; i++)
{
var pt = _points[i];

// Calculate the texture coordinate along the horizontal plane.
var u = (float)_points.Length / i;

var vertexIndex = i * 2;
// Create the vertex at the top of the landscape
// that is at the current X co-ordinate.
vertices[vertexIndex + 0] = new VertexPositionColorTexture(
new Vector3(pt.X, pt.Y, 0),
Color.White,
new Vector2(u, 0)
);
// And the bottom.
vertices[vertexIndex + 1] = new VertexPositionColorTexture(
new Vector3(pt.X, _height, 0),
Color.White,
new Vector2(u, 1)
);

// Create indicies that will make two triangles that
// fill the *right* of the current vertex.
if (i < _points.Length - 1)
{
var indexIndex = i * 6;
indicies[indexIndex + 0] = (short)(vertexIndex + 0); // Top left
indicies[indexIndex + 1] = (short)(vertexIndex + 1); // Bottom left
indicies[indexIndex + 2] = (short)(vertexIndex + 3); // Bottom right

indicies[indexIndex + 3] = (short)(vertexIndex + 0); // Top left
indicies[indexIndex + 4] = (short)(vertexIndex + 3); // Bottom right
indicies[indexIndex + 5] = (short)(vertexIndex + 2); // Top right
}
}

_vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColorTexture), vertices.Length, BufferUsage.WriteOnly);
_indexBuffer = new IndexBuffer(GraphicsDevice, IndexElementSize.SixteenBits, indicies.Length, BufferUsage.WriteOnly);

_vertexBuffer.SetData(vertices, 0, vertices.Length);
_indexBuffer.SetData(indicies, 0, indicies.Length);

// To draw:
GraphicsDevice.Indices = _indexBuffer;
GraphicsDevice.SetVertexBuffer(_vertexBuffer);
_basicEffect.Texture = _myTexture; // Your texture
_basicEffect.World = _worldMatrix;
foreach (var item in _basicEffect.CurrentTechnique.Passes)
{
item.Apply();
GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _vertexBuffer.VertexCount, 0, _indexBuffer.IndexCount);
}


This should create a vertex buffer that looks like this:

You should read up on BasicEffect if you want to learn how to set up textures during your rendering.

• This is the way I am going to do this, it allows me to set textures of each point. Thanks. – FrenchyNZ Oct 31 '11 at 23:28
• This works. Though I had to make a minor change. var indexIndex = i * 6; indicies[i + 0] = (short)(vertexIndex + 0); needs to be var indexIndex = i * 6; indicies[indexIndex + 0] = (short)(vertexIndex + 0); – FrenchyNZ Nov 1 '11 at 4:37
• Thanks for the feedback @Twitchy - I updated the answer. – Jonathan Dickinson Nov 1 '11 at 8:08
• No worries @Jonathan Dickinson . Currently, I am only using VertexPositionColor as I do not know how to use a texture with it. Could you elaborate on this some more? – FrenchyNZ Nov 1 '11 at 8:20
• @Twitchy added a link and updated the sample. I assume you already have it rendering - so all it comes down to is assigning the Texture property on your BasicEffect and making sure the texture coords are accurate (which mine should be). If you upload the barebones code somewhere I can look at it for you. – Jonathan Dickinson Nov 1 '11 at 9:39

You can create a Texture2D this way.

        Texture2D Mountain = new Texture2D( GraphicsDevice, Width, Height);
Color[] PixelData = new Color[Width * Height];

Color colA,colB;
float r;
for ( int x=0; x < Width && x < YourHeights.Length; x++ )
{
for ( int y=YourHeights[x]; y < Height; y++ )
{
// This is for colorize relative to height
// You can change or apply other texture
if (y<Height/3) {
colB = Color.IndianRed;
colA = Color.White;
r = 1.0f - y / (Height/3.0f);
}
else if (y<2*Height/3) {
colB = Color.Indigo;
colA = Color.IndianRed;
r = 1.0f - (y-Height/3.0f) / (Height/3.0f);
} else {
colB = Color.RosyBrown;
colA = Color.Indigo;
r = 1.0f - (y-2*Height/3.0f) / (Height/3.0f);
}

PixelData[x + y * Width] = Color.Lerp( colB, colA, r );
}
}
Mountain.SetData<Color>( PixelData );


Maybe you need to build more textures if your level is too long... or you can modify the texture scrolling it and adding new columns of pixels in the scroll side.