正如标题所示,我正在使用Perlin Noise制作高度图生成器。
我使用过这个网站的伪代码 - > http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
并转入C#代码。到目前为止,我已完成所有变量类型赋值,代码给出了输出。不幸的是我的输出看起来像这样 - >
如你所见,右边和下边有从黑到白的轻微渐变,但其他一切都是黑色的。
这是我的c#source - >
private void button1_Click( object sender, EventArgs e ) {
persistence = float.Parse( textBox4.Text );
NumberOfOctaves = Int32.Parse( textBox5.Text );
int width = Int32.Parse( textBox1.Text );
int height = Int32.Parse( textBox2.Text );
float zoom = float.Parse( textBox3.Text );
generate( width, height, zoom );
}
public float Noise( int x, int y ) {
long n = x + ( y * 57 );
n = ( long )Math.Pow( ( n << 13 ), n );
return ( float )( 1.0 - ( ( n * ( n * n * 15731 + 789221 ) + 1376312589 ) & 0x7fffffff ) / 1073741824.0 );
}
public float SmoothNoise( float x, float y ) {
float corners = ( Noise((int) (x-1), (int) (y-1)) + Noise((int) (x+1), (int) (y-1)) + Noise((int) (x-1), (int) (y+1)) + Noise((int) (x+1), (int) (y+1)) ) / 16;
float sides = ( Noise((int) (x-1), (int) y) + Noise((int) (x+1), (int) y) + Noise((int) x, (int) (y-1)) + Noise((int) x, (int) (y+1)) ) / 8 ;
float center = Noise( (int)x, (int)y ) / 4;
return corners + sides + center;
}
public float CosineInterpolate( float a, float b, float x ) {
double ft = x * 3.1415927;
double f = ( 1 - Math.Cos( ft ) ) * 0.5;
return (float)( ( a * ( 1 - f ) ) + (b * f) );
}
public float InterpolatedNoise( float x, float y ) {
// MessageBox.Show( x.ToString() );
int intX = ( int )x;
float fractX = x - intX;
int intY = ( int ) y;
float fractY = y - intY;
float v1 = SmoothNoise(intX, intY);
float v2 = SmoothNoise(intX + 1, intY);
float v3 = SmoothNoise(intX, intY + 1);
float v4 = SmoothNoise(intX + 1, intY + 1);
float i1 = CosineInterpolate(v1 , v2 , fractX);
float i2 = CosineInterpolate(v3 , v4 , fractX);
// MessageBox.Show( intX + "\n" + intY + "\n" + fractX + "\n" + fractY + "\n" + v1 + "\n" + v2 + "\n" + v3 + "\n" + v4 + "\n" + i1 + "\n" + i2 + "\n" + CosineInterpolate( i1, i2, fractY ) );
return CosineInterpolate(i1 , i2 , fractY);
}
public float PerlinNoise2D( float x, float y ) {
float total = 0;
float p = persistence;
int n = NumberOfOctaves;
for(int i = 0; i < n; i++ ) {
int frequency = (int)Math.Pow( 2, i );
// MessageBox.Show( Math.Pow( 2, i ).ToString() );
float amplitude = ( int )Math.Pow( p, i );
total = total + InterpolatedNoise(x * frequency, y * frequency) * amplitude;
}
return total;
}
private void generate( int sizeX, int sizeY, float zoom ) {
int zoomX = (int)( sizeX * zoom );
int zoomY = (int)( sizeY * zoom );
float max = int.MinValue;
float min = int.MaxValue;
float[,] nmap = new float[zoomX,zoomY];
Bitmap heightMap = new Bitmap(zoomX,zoomY);
for (int x=0; x<zoomX; x++) {
for (int y=0; y<zoomY; y++) {
// MessageBox.Show( PerlinNoise2D( x / zoom, y / zoom ).ToString() );
nmap[x,y] = PerlinNoise2D(x/zoom,y/zoom);
max = (max < nmap[x,y]) ? nmap[x,y] : max;
min = (min > nmap[x,y]) ? nmap[x,y] : min;
}
}
max = max-min;
for (int x=0; x<zoomX;x++) {
for (int y=0; y<zoomY;y++) {
int calc = (int) ( (nmap[x,y] - min) / max );
heightMap.SetPixel(x,y,Color.FromArgb(calc,calc,calc));
}
}
pictureBox1.Image = heightMap;
}
如果有人想要的话,我也可以将视觉工作室解决方案上传。
到目前为止,我已经发现Noise()函数出了问题,因为它返回-0,281 ...最多的时间。它应该返回介于-1.0和1.0之间的浮点数。 我已尝试使用其他随机函数,但输出每次都相同。
我希望你们可以帮助我,以及他们提出的建议。
答案 0 :(得分:2)
我在代码中发现了两个问题。
首先,您错误地将^
符号解释为幂函数
在原始源代码中,它是一个xor操作。所以行
n = ( long )Math.Pow( ( n << 13 ), n );
应该是
n = ( long )(( n << 13 ) ^ n);
其次,从噪音值创建彩色像素时,噪点在0..1范围内,颜色值应在0..255范围内,所以行
int calc = (int) ( (nmap[x,y] - min) / max );
应该是
int calc = (int) (( (nmap[x,y] - min) / max ) * 255);
此处的完整工作(控制台)示例:http://ideone.com/RGVf8J