- Home /
Perlin Noise Questions
Ok, so I've been experimenting with perlin noise and haven't had that much luck. I find there aren't many tutorials out their and articles such as this and this don't really go into enough detail. Anyway here's my problem:
I took the first article's script I linked and converted it into UnityScript:
var width : int;
var height : int;
var octaves : int;
var persistence : float;
function Start(){
PerlinNoise();
}
function PerlinNoise(){
var texture = new Texture2D(width, height, TextureFormat.ARGB32, false);
for(i = 0; i < octaves; i++){
var frequency = Mathf.Pow(2, i);
var amplitude = Mathf.Pow(persistence, i);
for(x = 0; x <= width; x++){
for(y = 0; y <= height; y++){
var noise = InterpolatedNoise(x * frequency, y * frequency) * amplitude;
var perlinColor = Color(noise, noise, noise, 0);
texture.SetPixel(x, y, perlinColor);
}
}
}
texture.Apply();
renderer.material.mainTexture = texture;
}
function InterpolatedNoise(x : int, y : int){
var initX = x;
var fractionX = x - initX;
var initY = y;
var fractionY = y - initY;
var v1 = SmoothNoise(initX, initY);
var v2 = SmoothNoise(initX + 1, initY);
var v3 = SmoothNoise(initX, initY + 1);
var v4 = SmoothNoise(initX + 1, initY + 1);
var i1 = Interpolate(v1, v2, fractionX);
var i2 = Interpolate(v3, v4, fractionX);
return Interpolate(i1, i2, fractionY);
}
function SmoothNoise(x : float, y : float){
corners = (Noise(x-1, y-1)+Noise(x+1, y-1)+Noise(x-1, y+1)+Noise(x+1, y+1))/16;
sides = (Noise(x-1, y)+Noise(x+1, y)+Noise(x, y-1)+Noise(x, y+1))/ 8;
center = Noise(x, y)/4;
return corners + sides + center;
}
function Interpolate(a : float, b : float, x : float){
ft = x * 3.1415927;
f = (1 - Mathf.Cos(ft)) * 0.5;
return a*(1-f) + b*f;
}
function Noise(x : int, y : int){
var n = x + y * 57;
n = (n<<13) ^ n;
var res = (1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
return res;
}
After doing that I wasn't surprised to find this function gave me a number overflow error:
function Noise(x : int, y : int){
var n = x + y * 57;
n = (n<<13) ^ n;
var res = (1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
return res;
}
I figured I would just use the random method, just to see what would happen. I know it's not pseudo but I figured at least something random would show up. After doing that I got this picture. Although It looks cool it obviously isn't perlin noise.
So basically what did I do wrong? My logic is telling me that the pixels are in that pattern because the random method inside the function I replaced isn't perlin. I can't use the other function though because it throws me a number overflow error as explained before. So what's a good perlin number generator that doesn't give me an error, or is their more to this? Could someone please help me out I want to be able to create noise like this.
Thanks!
Answer by Jeff Standen · Dec 17, 2011 at 12:02 PM
Here's the code that I use for Simplex noise in C#: https://gist.github.com/1489447
You can use it like the following:
SimplexNoiseGenerator noise = new SimplexNoiseGenerator();
string noise_seed = noise.GetSeed();
Vector3 coords = Vector3.one;
int octaves = 8;
int multiplier = 25;
float amplitude = 0.5f;
float lacunarity = 2f;
float persistence = 0.9f;
float n = noise.coherentNoise(coords.x,coords.y,coords.z,octaves,multipier,amplitude,lacunarity,persistence);
The return value for n
will be a float between -1f and +1f. If you assume zero is the middle of your range, then the negative values could be depth (oceans, valleys) and the positive values could be height (mountains). Just multiply the value by whatever you want the deviation to be and add it to the median.
For another example, if you want noise values to scale from 0-255 in an image, you could pick a median around 127.5 and then add (`n*127.5`). That will give you a gray scale cloudy image like the one you're looking for.
You can tweak the parameters for coherentNoise()
to get things on the scale you're looking for. Magnification
is a useful parameter for tweaking, as is lacunarity
. Depending on your needs, you may be able to use fewer than 8 octaves, but that's often a reason why your output won't look like the familiar cloudy "coherent" noise.
I built a little GUI in Unity to tweak the Simplex parameters with sliders until things look good for whatever my use is at the time. I've used noise to generate procedural textures, as well as to provide terrain generation for infinite worlds that can be serialized in a small number of bytes and sent over the network to other players to generate the same maps
Good luck!
Thanks for the answer but I have 2 quick questions. Are you sure this is 2D? I probably should have made that more apparent but in the coherentNoise function there is a parameter called "z" and your calling it with coords.z.
Also where would the loop be for looping through each pixel? I would loop this line with the x and y variables changing right?:
float n = noise.coherentNoise(coords.x,coords.y,coords.z,octaves,multipier,amplitude,lacunarity,persistence);
The reason I doubt it is because there is a z parameter so I'm not sure what to do for that since I won't be using it. I'm just not sure how to implement looping through each pixel with that code.
@Jeff Standen, could you make your GUI in Unity to tweak the Simplex parameters available in the same way you did with the Simplex code? Thanks in advance.
Answer by Jeff Standen · Dec 18, 2011 at 12:39 AM
Hey there! You can just imagine that the 3D noise has infinite 2D layers. Just set the z
parameter to 0. You could set it to any value, as long as it's constant. You're right, to draw a 2D image you'd just change x
and y
and then multiply the result n
by some number to determine which color to use.
[1] ![Hi there, old topic I know. But I tried your noisegenerator, but the result looks kinda weird. It's noisy, yeah, but it's like a bunch of straight lines through each other, rather than a perlin noise look. any idea how to fix that?]
[1]: /storage/temp/9446-simplexnoise.png
$$anonymous$$ay be a bit late, but I just saw this and thought I'd leave a reply. Are you sure the UV coords of that mesh aren't just stretching? Try using a checker pattern texture to check if the UV's have streching in them.
Your answer
Follow this Question
Related Questions
i want to spawn randomly 1 Answer
Why does Perlin-generated Texture lose gradient when with colour? 1 Answer
Randomly Generate Game Object 1 Answer
Choose random prefabs from list? 1 Answer
Using noise as texture 2 Answers