我正在尝试创建一个Worley Noise函数。我环顾四周,阅读了Steven Worley的原始论文并写下了我的实现。但输出似乎不正确。我期待看到类似的东西。
但它输出了这个。
我不确定我做错了什么。我在网上看过其他人的节目,我也是这样做的。这是代码。
float WorleyNoise::noise( Vector3 input ) {
unsigned int lastRandom;
unsigned int numberFeaturePoints;
Vector3 randomDiff;
Vector3 featurePoint;
int cubeX;
int cubeY;
int cubeZ;
float distanceArray[ 3 ];
for ( int i = 0; i < 3; i++ ) {
distanceArray[ i ] = 6666.0f;
}
int evalX = ( int ) floorf( input.m_x );
int evalY = ( int ) floorf( input.m_y );
int evalZ = ( int ) floorf( input.m_z );
for ( int i = -1; i < 2; ++i ) {
for ( int j = -1; j < 2; ++j ) {
for ( int k = -1; k < 2; ++k ) {
cubeX = evalX + i;
cubeY = evalY + j;
cubeZ = evalZ + k;
lastRandom = lcg_random( hash( ( unsigned int ) ( cubeX + m_seed ), ( unsigned int ) cubeY, ( unsigned int ) cubeZ ) );
numberFeaturePoints = lookup( lastRandom );
for ( unsigned int l = 0; l < numberFeaturePoints; ++l ) {
lastRandom = lcg_random( lastRandom );
randomDiff.m_x = ( float ) lastRandom / 0x100000000;
lastRandom = lcg_random( lastRandom );
randomDiff.m_y = ( float ) lastRandom / 0x100000000;
lastRandom = lcg_random( lastRandom );
randomDiff.m_z = ( float ) lastRandom / 0x100000000;
featurePoint.m_x = randomDiff.m_x + ( float ) cubeX;
featurePoint.m_y = randomDiff.m_y + ( float ) cubeY;
featurePoint.m_z = randomDiff.m_z + ( float ) cubeZ;
insert( distanceArray, euclidian_distance( input, featurePoint ) );
}
}
}
}
return Utility::clampf( combine_function_1( distanceArray ), 0.0f, 1.0f );
}
unsigned int WorleyNoise::hash( unsigned int i, unsigned int j, unsigned int k ) {
return ( unsigned int ) ( ( ( ( ( ( OFFSET_BASIS ^ ( unsigned int ) i ) * FNV_PRIME ) ^ ( unsigned int ) j ) * FNV_PRIME ) ^ ( unsigned int ) k ) * FNV_PRIME );
}
unsigned int WorleyNoise::lcg_random( unsigned int last ) {
return ( unsigned int ) ( ( 1103515245 * last + 12345 ) % 0x100000000 );
}
void WorleyNoise::insert( float arr[] , float value ) {
float temp = 0.0f;
for ( int i = 2; i >= 0; i-- ) {
if ( value > arr[ i ] ) {
break;
}
temp = arr[ i ];
arr[ i ] = value;
if ( i + 1 < 3 ) {
arr[ i + 1 ] = temp;
}
}
}
unsigned int WorleyNoise::lookup( unsigned int value ) {
value = value & 0xffffffff;
if ( value < 393325350 )
return 1;
if ( value < 1022645910 )
return 2;
if ( value < 1861739990 )
return 3;
if ( value < 2700834071 )
return 4;
if ( value < 3372109335 )
return 5;
if ( value < 3819626178 )
return 6;
if ( value < 4075350088 )
return 7;
if ( value < 4203212043 )
return 8;
return 9;
}
float WorleyNoise::euclidian_distance( Vector3 p1, Vector3 p2 ) {
return ( p1.m_x - p2.m_x ) * ( p1.m_x - p2.m_x ) + ( p1.m_y - p2.m_y ) * ( p1.m_y - p2.m_y ) + ( p1.m_z - p2.m_z ) * ( p1.m_z - p2.m_z );
}
float WorleyNoise::combine_function_1( float arr[] ) {
return arr[ 0 ];
}
然后我使用pngwriter输出结果。
void WorleyNoise::to_png( const std::string &file, unsigned int width, unsigned int height ) {
pngwriter png( width, height, 0, file.c_str() );
for ( unsigned int i = 0; i < width; i++ ) {
for ( unsigned int j = 0; j < height; j++ ) {
float value = noise( Vector3( i, j, 0 ) );
png.plot( i, j, ( double ) value, ( double ) value, ( double ) value );
}
}
png.close();
}
那么这里出了什么问题?我看了一遍,特别是在this tutorial,并且无法弄清楚它为什么输出不正确。非常感谢任何帮助,谢谢。