Симплексный шум черепицы?
Меня интересует (как любитель) генерация псевдослучайного шума, в частности алгоритмов Perlin и Simplex. Преимущество Simplex заключается в скорости (особенно при больших размерах), но Perlin может быть сравнительно легко выложен плиткой. Мне было интересно, если кто-нибудь знал о алгоритме симплексный лист? Фиксированная размерность в порядке, общая - лучше; псевдокод в порядке, с / с ++ лучше.
4 ответа
Просто возьмите свой шум так же, как в Perlin, только после перекоса. Вы можете сделать это, изменив часть, которая получает перестановки, чтобы сделать мод 256 (или & 255, независимо от того, что вы используете) после того, как (а не до) вы добавили к смещениям, чтобы получить другие углы из базового угла. Это модифицированный бит кода в HLSL:
uint3 iIdx0 = p0SI % 256;
uint3 iIdx1 = (p0SI + pI1) % 256;
uint3 iIdx2 = (p0SI + pI2) % 256;
uint3 iIdx3 = (p0SI + 1.0f) % 256;
uint iGI0 = gPerm[ iIdx0.x + gPerm[ iIdx0.y + gPerm[ iIdx0.z ] ] ] % 12;
uint iGI1 = gPerm[ iIdx1.x + gPerm[ iIdx1.y + gPerm[ iIdx1.z ] ] ] % 12;
uint iGI2 = gPerm[ iIdx2.x + gPerm[ iIdx2.y + gPerm[ iIdx2.z ] ] ] % 12;
uint iGI3 = gPerm[ iIdx3.x + gPerm[ iIdx3.y + gPerm[ iIdx3.z ] ] ] % 12;
p0SI - это точка угла 0, а pI2 и PI2 - векторы для угла один и угла 2, рассчитанные обычным способом. Обратите внимание, что в HLSL скаляры автоматически переносят векторы в смешанных операциях, так что, например, 1.0f на самом деле (1.0,1.0,1.0). Я только что разобрался с этой плиткой, но, по-видимому, она работает. Если вам нужно затенить большую планету или какое-то дерьмо, но иметь только одну точность на вашей карте, есть еще несколько шагов. Ударь меня.
Изменить: вы знаете, подумав об этом еще немного, я не думаю, что вам нужно что-то менять. Я думаю, что это автоматически в 256 единиц, как реализовано.
Даже если прошло несколько лет, этот вопрос остается одним из лучших результатов в Google.
В симплексном шуме x и y из прямой (ортонормированной) сетки искажаются, чтобы найти симплекс, в котором находится точка (треугольник в 2D), поэтому с обычными методами листов (%255 или чем-то еще), он ДЕЛАЕТ плитку, но плитки на Перекошенные координаты, то есть это плитки по диагонали, что совершенно бесполезно.
Простое решение, которое я нашел, состоит в том, чтобы "отогнуть" результат, так чтобы исходные X и Y сначала были перекошены "влево", затем алгоритм переместит их "вправо", и окончательный результат будет заново выровнен по нескошенной сетке.
Если, например, ваша симплексная реализация похожа на SimplexNoise.java, которую вы можете найти везде в сети, она искажает сетку, используя:
var F2 = 0.5*(Math.sqrt(3.0)-1.0);
var s = (xin+yin)*F2; // Hairy factor for 2D
var i = Math.floor(xin+s);
var j = Math.floor(yin+s);
Вы можете просто "предварительно наклонить" его в противоположном направлении в точке входа метода:
var G2 = (3.0-Math.sqrt(3.0))/6.0;
var t = (xin+yin)*G2;
xin-=t;
yin-=t;
К сожалению, он производит странно выглядящий эффект (то есть выглядит немного искаженным:D), что обычно не является проблемой, но зависит от того, для чего вам нужен этот шум.
Поскольку это было проблемой для меня, я попытался применить этот "обратный перекос" только к нескольким октавам, тем, которые больше весят в конечном результате, и вместо этого использовал интерполяцию для "более легких" октав. Это решение дало мне удовлетворительную мозаику, основанную на симплексном шуме Перлина, потому что интерполяция на всех октавах привела бы к слишком большому затуханию на границах мозаики, и когда добавление большего количества октав без искусственного перекоса, эффект внешнего вида скрывается под дополнительным шумом.
Недавно я нуждался в симплексном шуме и столкнулся с этим вопросом.
Для шума мозаичного изображения, используя любую шумовую функцию, вы можете линейно интерполировать дополнительные выборки мозаичного изображения:
Ftileable(x, y) = (
F(x, y) * (w - x) * (h - y) +
F(x - w, y) * (x) * (h - y) +
F(x - w, y - h) * (x) * (y) +
F(x, y - h) * (w - x) * (y)
) / (wh)
где F() - ваша функция шума. Обратите внимание, что x, y должны быть координатами в пределах отдельной плитки: x в [0, w), y в [0, h). Вы можете использовать что-то вроде tileX = x - Math.Floor(x / w) * w или fmod().
Если производительность критична или для более высоких измерений, это может быть не тот путь, потому что он требует двухмерных поисков для измерения D. Это также привело к более низким значениям для центров плиток для меня.
Взято из: http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html