Я пытаюсь создать базовое значение шумовой функции. Я дошел до того, что он выводит его, но в выводе появляются неожиданные артефакты, такие как диагональные прерывистые линии и пятна. Я просто не могу найти причину. Может ли кто-нибудь, пожалуйста, взглянуть на это, чтобы увидеть, если я где-то не так.
Прежде всего, вот три изображения, которые он выводит с большим увеличением на каждом.
//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;
}
Некоторые из артефактов являются результатом линейной интерполяции. Использование метода интерполяции более высокого порядка поможет, но это решит только часть проблемы. Грубо говоря, резкие переходы в сигнале могут привести к появлению артефактов.
Дополнительные артефакты возникают в результате распределения начальных значений шума (т. Е. Значений, между которыми вы интерполируете) через равные интервалы — в данном случае сетку. Самый высокий & самые низкие значения будут только когда-либо происходить в этих точках сетки — по крайней мере, при использовании линейной интерполяции. Грубо говоря, паттерны в сигнале могут привести к появлению артефактов. Два возможных способа решения этой части проблемы, которые я знаю, это либо использование нелинейной интерполяции &/ или случайным образом подталкивая координаты начальных шумовых значений, чтобы нарушить их регулярность.
У Libnoise есть объяснение генерирование когерентного шума который охватывает эти проблемы & решения более подробно с некоторыми хорошими иллюстрациями. Вы также можете посмотреть на источник, если вам нужно посмотреть, как он справляется с этими проблемами. И как уже упоминалось Ричард-Тингл, симплексный шум был разработан, чтобы исправить проблемы с артефактами, присущие шуму Перлина; немного сложнее разобраться, но это надежная техника.
Других решений пока нет …