Worley噪音不能产生正确的输出

时间:2015-11-25 17:39:43

标签: c++ procedural-generation

我正在尝试创建一个Worley Noise函数。我环顾四周,阅读了Steven Worley的原始论文并写下了我的实现。但输出似乎不正确。我期待看到类似的东西。

enter image description here

但它输出了这个。

enter image description here

我不确定我做错了什么。我在网上看过其他人的节目,我也是这样做的。这是代码。

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,并且无法弄清楚它为什么输出不正确。非常感谢任何帮助,谢谢。

0 个答案:

没有答案