Pull to refresh

Comments 14

Хороший туториал, в принципе. Когда-то давно пользовался шумом Перлина для генерации текстур планет, примерно половину из описанного здесь использовал. Но было это за три года до оригинала этой статьи. Правда, залитый флэш выжил… www.fastswf.com/EkwUOdk
У этого метода было замечательное преимущество в скорости [...] но его недостатком был скучный ландшафт. В частности из-за невозможности генерировать нависающие над землей выступы.

Теперь (примерно с Beta 1.3) пришлось перейти на похожую систему, использующую трёхмерный шум Перлина. Теперь уже не генерируется «высота земли». Значение шума было рассматривается как «плотность», и все блоки с плотностью меньше 0 становятся воздухом, а блоки с плотностью больше или равной 0 — землёй. Чтобы нижний слой был твёрдый, а верхний — нет, к полученному результату прибавляется высота (смещение относительно уровня моря).

Minecraft Wiki

Было бы гораздо интереснее понять как работает собственно сама функция noise(x, y). Ковырять исходники библиотеки это, конечно, могло бы быть весело, но математический аппарат простым языком до сих пор на русском языке не описан.
Спасибо, но там тоже этому уделено два абзаца. Какие-то вектора.
Кто-нибудь может объяснить, каким боком приплетены вектора в ГПСЧ?
Вы хотите описание математики за шумом Перлина, но говорите «какие-то вектора». Так уж случилось, что вектора крайне полезный термин в описании алгоритма генерации карты шума, и любое описание будет их включать.
1. Так нет описания. Есть кусок кода с без объяснения работы.
2. Суть шума Перлина мне понятна. Непонятен метод «сырых» случайных данных в noise();
private float[] GetPseudoRandomGradientVector(int x, int y)
    {
        int v = (int)(((x * 1836311903) ^ (y * 2971215073) + 4807526976) & 1023);
        v = permutationTable[v]&3;

        switch (v)
        {
            case 0:  return new float[]{  1, 0 };
            case 1:  return new float[]{ -1, 0 };
            case 2:  return new float[]{  0, 1 };
            default: return new float[]{  0,-1 };
        }
    }

Вот эта часть?

Интересует математический аппарат функции noise(x), noise(x,y) (и т.д. размерностей), которая возвращает одно и то же случайное значение для одних и тех же аргументов (координат).
В известном переводе на Хабре это реализуется какой-то чехардой с числами, что Кнут в гробу переворачивается:

function Noise(integer x)
x = (x<<13) ^ x;
return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & 7fffffff) / 1073741824.0);
end function

function Noise(integer x, integer y)
n = x + y * 57
n = (n<<13) ^ n;
return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 7fffffff) / 1073741824.0);
end function


Но это, конечно, несерьезно. Таким образом, меня интересует, повторюсь, математический аппарат функции, которая возвращает одно и то же случайное значение для одних и тех же координат. Ни одна из статей на Хабре не описывает данную проблему.
Всего лишь берется быстрорастущая функция от некоего Х, меняющаяся не менее чем на 1/2 от 0xfffffff при приращении Х на единицу, отрезаются старшие биты и нормируется результат до интервала 0-1. Коэффициенты подбираются достаточно большими, чтобы влиять на результат, и взаимно простыми, чтобы исключить вероятность сложения высоких гармоник с порождением периодичности получившегося результата на каком-либо участке по Х. Плюс в начале, чтобы не брать заранее известные околонулевые величины, этот Х смещается подальше от нуля.
Согласитесь, это стоило бы того, чтобы описать. К тому же, предполагаю, это не самый оптимальный вариант, а с точки зрения «случайности» — вообще караул. Здесь очевидна попытка сделать нечто по мотивам линейного конгруэнтного ГПСЧ, но действительно продуманных и обоснованных описаний мне найти так и не удалось.
Ну да, это ГПСЧ, причем без возможности инициализации. По-хорошему, тут бы вихрь Мерсенна какой-нибудь, он тоже ГПСЧ стопроцентно повторяемый, но имеем что имеем. Ну или генерировать коэффициенты для этого noise2() случайным образом и тащить их в классе шума. Думаю, простая функция тут для «quick and dirty» варианта псевдослучайных чисел с гарантированным повторением вывода, для шейдеров или типа того.
То, что «quick and dirty» понятно было с самого начала.

Должна (обязана) существовать функция (алгоритм), при которой качество случайности noise(x = 1 to 1000) будет не хуже, чем тысяча последовательных вызовов random() любого адекватного ЯП.
О реализации математике этой функции и был мой изначальный вопрос. Увы, но похоже, что что нет вариантов, кроме как сделать заранее большой массив случайных чисел на пару десятков мегабайт, а noise(x) будет возвращать число по индексу.
Sign up to leave a comment.

Articles