【问题标题】:Artefacts in Interpolated Value Noise插值噪声中的伪影
【发布时间】:2013-07-07 20:40:18
【问题描述】:

我正在尝试创建一个基本的值噪声函数。我已经达到了输出它的地步,但是在输出中会出现意想不到的伪影,例如对角线不连续的线条和模糊。我似乎无法找到导致它的原因。有人可以看看它,看看我是否在某个地方出错了。

首先,这是它输出的三张图像,每张图像的放大倍数都更大。

//data members
float m_amplitude, m_frequency;
int m_period;  //controls the tile size of the noise
vector<vector<float> m_points; //2D array to store the lattice

//The constructor generates the 2D square lattice and populates it.
Noise2D(int period, float frequency, float amplitude)
{
    //initialize the lattice to the appropriate NxN size
    m_points.resize(m_period);
      for (int i = 0; i < m_period; ++i)
        m_points[i].resize(m_period);

    //populates the lattice with values between 0 and 1
    int seed = 209;
            srand(seed);
    for(int i = 0; i < m_period; i++)
    {
        for(int j = 0; j < m_period; j++)
        {
            m_points[i][j] = abs(rand()/(float)RAND_MAX);
        }
    }
}


//Evaluates a position
float Evaluate(float x, float y)
{
    x *= m_frequency;
    y *= m_frequency;

    //Gets the integer values from each component
    int xFloor = (int) x;
    int yFloor = (int) y;

    //Gets the decimal data in the range of [0:1] for each of the components for interpolation
    float tx = x - xFloor;
    float ty = y - yFloor;

    //Finds the appropriate boundary lattice array indices using the modulus technique to ensure periodic noise.
    int xPeriodLower = xFloor % m_period;
    int xPeriodUpper;
    if(xPeriodLower == m_period - 1) 
        xPeriodUpper = 0; 
    else    
        xPeriodUpper = xPeriodLower + 1;

    int yPeriodLower = yFloor % m_period;
    int yPeriodUpper;
    if(yPeriodLower == m_period - 1) 
        yPeriodUpper = 0; 
    else    
        yPeriodUpper = yPeriodLower + 1;

    //The four random values at each boundary. The naming convention for these follow a single 2d coord system 00 for bottom left, 11 for top right
    const float& random00 = m_points[xPeriodLower][yPeriodLower];
    const float& random10 = m_points[xPeriodUpper][yPeriodLower];
    const float& random01 = m_points[xPeriodLower][yPeriodUpper];
    const float& random11 = m_points[xPeriodUpper][yPeriodUpper];

    //Remap the weighting of each t dimension here if you wish to use an s-curve profile.
    float remappedTx = tx;
    float remappedTy = ty;

    return MyMath::Bilinear<float>(remappedTx, remappedTy, random00, random10, random01, random11) * m_amplitude;
}

这是它所依赖的两个插值函数。

template <class T1>
static T1 Bilinear(const T1 &tx, const T1 &ty, const T1 &p00, const T1 &p10, const T1 &p01, const T1 &p11)
{
    return Lerp(    Lerp(p00,p10,tx),
            Lerp(p01,p11,tx),
            ty);
}

template <class T1> //linear interpolation aka Mix
static T1 Lerp(const T1 &a, const T1 &b, const T1 &t)
{
    return a * (1 - t) + b * t;
}

【问题讨论】:

  • 随机点阵中出现的随机特征...谁能想到?如果这是不同种子的可重复问题,那么也许有问题。您应该显示您的 MyMath::Random 函数。那里的“种子”一词有些可疑。播种通常发生一次。
  • 为了更清楚一点,我修改了代码以使用内置的种子 rand 函数,它仍然输出相同的图像。
  • 我必须承认我没有读过 C++,但看起来你只包含了一个八度,这是你想要的吗? (一个八度音程总是会产生静态,当你“缩小”它看起来像平滑的静态)。如果这是您的愿望,我不确定我是否真的看到任何伪影,但柏林噪声显然有一些小伪影。尝试使用单纯形噪声来减少伪影(但提高数学复杂性)

标签: c++ graphics interpolation noise perlin-noise


【解决方案1】:

某些伪影是线性插值的结果。使用更高阶的插值方法会有所帮助,但它只能解决部分问题。粗略地说,信号中的急剧转变会导致伪影。

以相等的间隔分布起始噪声值(即您在其中插值的值)会产生额外的伪影 - 在本例中为网格。最高和最低值只会出现在这些网格点上——至少在使用线性插值时是这样。粗略地说,信号中的模式会导致伪影。我知道解决这部分问题的两种潜在方法是使用非线性插值和/或随机微调起始噪声值的坐标以打破它们的规律性。

Libnoise 对generating coherent noise 进行了解释,其中通过一些精美的插图更深入地涵盖了这些问题和解决方案。如果您需要了解它如何处理这些问题,您也可以查看源代码。正如richard-tingle 已经提到的,simplex noise 旨在纠正 Perlin 噪声中固有的伪影问题;虽然有点难以理解,但这是一项可靠的技术。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    • 2014-06-14
    相关资源
    最近更新 更多