Help Me With My 3D Perlin Noise

Started by
2 comments, last by jdub 13 years ago
Here's a link to a video of it:


Although it might be kind of hard to make out in the vid, my noise function looks like a slideshow in that it has a smooth blurry transition. However, I'm not getting the smooth flowing noise that I should be getting... Is anything obviously wrong with my implementation from looking at the video?

Here is the relevant code for my noise implementation (Sorry, it is a little hard to read. I might clean it up and repost in a little while):



//The main noise function

public static double Noise(int x, int y, double z)
{
int numLevels = 3;
double frequency = 1d;
double amplitude = 1d;
double persistence = 0.5d;
double level = 1d/ Math.Pow(2, numLevels - 1);
double value = 0;

//create each level
for (int i = 0; i < numLevels; i++)
{
value += noiseAtLvl(x , y , z , frequency * level, amplitude);

frequency *= 2d;
amplitude *= persistence;
level *= 2d;
}

return value;
}

private static double noiseAtLvl(double x, double y, double z, double frequency, double amplitude)
{
return interpolateNoise3D(x * frequency, y * frequency, z) * amplitude;
}

/// <summary>
/// Smooth a point based on the colors of its surrounding pixels and a little randomness
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
private static double smoothNoise3D(int x, int y, int z)
{
//lvl 0 The noise level below the current one
double corners0 = (noise3D(x - 1, y - 1, z - 1) + noise3D(x + 1, y - 1, z - 1) + noise3D(x + 1, y + 1, z - 1) + noise3D(x - 1, y + 1, z - 1)) / 16d;
double sides0 = (noise3D(x + 1, y, z - 1) + noise3D(x - 1, y, z - 1) + noise3D(x, y + 1, z - 1) + noise3D(x, y - 1, z - 1)) / 8d;
double pix0 = noise3D(x, y, z - 1) / 4d;

double level0 = corners0 + sides0 + pix0;

//lvl current
double corners = (noise3D(x - 1, y - 1, z) + noise3D(x + 1, y - 1, z) + noise3D(x + 1, y + 1, z) + noise3D(x - 1, y + 1, z)) / 16d;
double sides = (noise3D(x + 1, y, z) + noise3D(x - 1, y, z) + noise3D(x, y + 1, z) + noise3D(x, y - 1, z)) / 8d;
double pix = noise3D(x, y, z) / 4d;

double levelCurrent = corners + sides + pix;

//lvl 1 The noise level above the current one
double corners1 = (noise3D(x - 1, y - 1, z + 1) + noise3D(x + 1, y - 1, z + 1) + noise3D(x + 1, y + 1, z + 1) + noise3D(x - 1, y + 1, z + 1)) / 16d;
double sides1 = (noise3D(x + 1, y, z + 1) + noise3D(x - 1, y, z + 1) + noise3D(x, y + 1, z + 1) + noise3D(x, y - 1, z + 1)) /8d;
double pix1 = noise3D(x, y, z + 1) / 4d;

double level1 = corners1 + sides1 + pix1;

return ( ( level0 / 3d) + (levelCurrent / 3d ) + (level1 / 3d) );
}

/// <summary>
/// Smooth noise point more through interpolation
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
private static double interpolateNoise3D(double x, double y, double z)
{
int intX = (int)Math.Floor(x);
int intY = (int)Math.Floor(y);
int intZ = (int)Math.Floor(z);

double fractionX = x - intX;
double fractionY = y - intY;
double fractionZ = z - intZ;

double ulcorner0 = smoothNoise3D(intX, intY, intZ);
double urcorner0 = smoothNoise3D(intX + 1, intY, intZ);
double blcorner0 = smoothNoise3D(intX, intY + 1, intZ);
double brcorner0 = smoothNoise3D(intX + 1, intY + 1, intZ);
double xlvl0_1 = cosInterpolate(ulcorner0, urcorner0, fractionX);
double xlvl0_2 = cosInterpolate(blcorner0, brcorner0, fractionX);

double lvl0 = cosInterpolate(xlvl0_1, xlvl0_2, fractionY);

double ulcorner1 = smoothNoise3D(intX, intY, intZ + 1);
double urcorner1 = smoothNoise3D(intX + 1, intY, intZ + 1);
double blcorner1 = smoothNoise3D(intX, intY + 1, intZ + 1);
double brcorner1 = smoothNoise3D(intX + 1, intY + 1, intZ + 1);
double xlvl1_1 = cosInterpolate(ulcorner1, urcorner1, fractionX);
double xlvl1_2 = cosInterpolate(blcorner1, brcorner1, fractionX);

double lvl1 = cosInterpolate(xlvl1_1, xlvl1_2, fractionY);

return cosInterpolate(lvl0, lvl1, fractionZ);
}

J.W.
Advertisement
bump... anyone?
J.W.
Any chance that the problem is z not being multiplied by frequency in noiseAtLvl?
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other player's eyes with his King.
Ah... that fixed the problem. Thanks!
J.W.

This topic is closed to new replies.

Advertisement