Here's how I've been handling it.
1: use the same generator. This is not really optional. You need the same noise function if you want to generate seamless noise between textures, chunks, etc. The seed and other variables should NOT be modified outside of the initial startup.
2: Continue on with incrementing the X/Y/Z in relation to your first texture.
For example... lets say you are creating 2 64x64 pixel textures side by side. Your first texture is going to look something along the lines of...
for(int y = 0; y < 64; y++) for(int x = 0; x < 64; x++) noiseArray[y * 64 + x] = generator.GetValue(x, y, 0);
Now... we have that generated but what happens for our second texture? Simple! Just continue boosting x and y.
noiseArray[y * 64 + x] = generator.GetValue(x, y + 64, 0); //this texture is to be placed at y++ from first one
Now.. that's all well and good but especially if you need large maps, this may not be your best approach. Personally I'd consider each texture as taking up 1 coord. Therefor each pixel, block or however you want to think of it inside that texture is going to be 1/Dimensions.X or 1/Dimensions.Y
Simply alter your noise function (or output returned from it) so that it will accept these much smaller increments.
Hope that helps.
Here's a very, very basic bit of code I whipped up for a noisemap test in XNA.
Texture2D One, Two; Point Dimensions = new Point(500, 500); void GenerateHeightmaps() { generator = new GeneralTerrain(new Random().Next(int.MaxValue / 2)); One = GenerateTexture(new Vector3(0, 0, 0)); Two = GenerateTexture(new Vector3(0, 1, 0)); } Texture2D GenerateTexture(Vector3 worldLocation) { Color[] noise = new Color[Dimensions.X * Dimensions.Y]; for (float x = 0; x < Dimensions.X; x++) for (float y = 0; y < Dimensions.Y; y++) { int cval = GenerateHeight(worldLocation, new Vector2(x, y)); noise[(int)(y + x * Dimensions.Y)] = new Color(cval, cval, cval); } Texture2D text = new Texture2D(GraphicsDevice, Dimensions.X, Dimensions.Y); text.SetData(noise); return text; } int GenerateHeight(Vector3 worldLocation, Vector2 blockLocation) { Point loc = new Point((int)(blockLocation.X + worldLocation.X * Dimensions.Y), (int)(blockLocation.Y + worldLocation.Y * Dimensions.Y)); return generator.GetData(loc.X, loc.Y); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here spriteBatch.Begin(); spriteBatch.Draw(One, Vector2.Zero, Color.White); spriteBatch.Draw(Two, new Vector2(Dimensions.Y + 1, 0), Color.White); spriteBatch.End(); base.Draw(gameTime); }
And the Simple GeneralTerrain class to configure the generator
public class GeneralTerrain { Perlin generator; public GeneralTerrain(int seed) { generator = new Perlin(); generator.Seed = seed; generator.NoiseQuality = NoiseQuality.Standard; generator.OctaveCount = 5; generator.Frequency = .01; } public int GetData(double x, double y) { return (int)(generator.GetValue(x, y, 0) * 128 + 100); } }