Пошук та розгортання шуму
Генерація правдоподібного ландшафту починається з шуму градієнтів (Perlin-стиль або сімплексний шум): це гладка, псевдовипадкова функція позиції без різких стрибків, яка генерується детерміновано за фіксованого насіння, щоб однакові (x, y) завжди повертали однаковий висоту. Навіділ шуму сам по собі виглядає як гладкі, рівномірні, без особливих ознак горила, нічого схожого на справжній гірський хребет, який має деталі на різних масштабах одночасно.
Фрактальна Броунівська Рух: Надкластери
Фрактальна Броунівська Рух (fBm) вирішує це, шляхом підсумовування кількох октав одного шумового функціоналу з наростаючою частотою та зменшуваною амплітудою — кожна октава додає більше деталей, як додавання каменів на вершині пагорбів, пагорбів на вершині гірського хребта:
функція fbm(x, y, октави, лакунарність, коефіцієнт) { let загальна = 0, амплітуда = 1, частота = 1, максимальне значення = 0; для (і з i = 0 до октави - 1) { загальна += noise(x * частота, y * частота) * амплітуда; максимальне значення += амплітуда; амплітуда *= коефіцієнт; // зазвичай 0.5 - кожна октава слабша частота *= лакунарність; // зазвичай 2.0 - кожна октава більш детальна } повернути загальну / максимальне значення; // нормалізовано до приблизно [-1, 1] }
Лакуарність контролює, наскільки детальнішою стає кожна наступна октава (2.0 подвоює частоту кожного разу, класичний вибір); коефіцієнт (іноді називають «персистентністю») контролює, як швидко падає амплітуда, і, отже, наскільки «грубим» виглядає рельєф — коефіцієнт близько 0.5 дає природні гори, а вищий коефіцієнт зберігає високу частоту деталей гучними та створює химерний, чужорідний ландшафт. Ця багатошарова конструкція шуму приблизно відповідає 1/f шуму (рожевому шуму), статистичному текстурі, що вимірюється в реальних узбережжях і силуетах гірських хребтів, тому fBm рельєф здається природним, а не випадковим.
function fbm(x, y, octaves, lacunarity, gain) {
let total = 0, amplitude = 1, frequency = 1, maxValue = 0;
for (let i = 0; i < octaves; i++) {
total += noise(x * frequency, y * frequency) * amplitude;
maxValue += amplitude;
amplitude *= gain; // typically 0.5 - each octave weaker
frequency *= lacunarity; // typically 2.0 - each octave finer
}
return total / maxValue; // normalised to roughly [-1, 1]
}
З висоти до біому: рельєфне затімання та кольори
Висотовий профіль сам по собі є сірим утворенням; стає читабельною місцевістю, коли його затіняють та фарбують. Рельєфне затімання обчислює локальну поверхневу нормаль з різниць висот між сусідніми клітинними комірками і множить її на фіксовану напрямку сонця, освітлюючи схили, що дивляться на світло, та затемнюючи ті, що дивляться в бік. Ця ж техніка використовується картографами з 19 століття. Колір біомів потім встановлює порогові значення висоти (і іноді незалежного шумового шару для вологості) у смуги: глибокий блакитний нижче рівня моря, пісок біля узбережжя, зелений на середній висоті, сірий камінь та білий сніг на вершинах.
Гідрологічна ерозія: роблячи шум таким, що виглядає поношеним
Необроблений fBm ніколи не зношується, тому його хребти завжди мають рівномірно м’які лінії у порівнянні з реальним рельєфом, створеним мільйонами років потоку води. Гідрологічна ерозія безпосередньо моделює цей процес: кидайте тисячі віртуальних крапель води на карту висот, і дозвольте кожній з них слідувати найближчому до знизу градієнту, збираючи відкладення там, де потік швидкий у крутих областях, та відкладаючи їх там, де він сповільнюється у рівнинних ділянках.
Для кожної з N крапель: pos = випадкова точка на карті Поки крапля не зупиниться: grad = градієнт висоти(pos) // напрямок найстійкішого спуску pos += -grad * швидкість capacity = швидкість * вода * коефіцієнт нахилу Якщо відкладень достатньо (> capacity): відкласти(pos, відкладення - capacity) Інакше: зношувати(pos, capacity - відкладення) Швидкість = оновлення з втрати висоти (закон збереження енергії) Вода *= випаровування // крапля зрештою зупиниться
for each of N droplets:
pos = random point on the map
while droplet has not stopped:
grad = heightGradient(pos) // steepest descent direction
pos += -grad * speed
capacity = speed * water * slopeFactor
if sediment > capacity: deposit(pos, sediment - capacity)
else: erode(pos, capacity - sediment)
speed = update from height loss (energy conservation)
water *= evaporation // droplet eventually stops
Часті запитання
Чому рельєф, згенерований одним шаром шуму, виглядає нереалістично?
Один шар шуму має деталізацію лише на одній просторовій шкалі, тому він виглядає як гладкі, без особливих рис пагорби. Реальний рельєф має структуру на багатьох масштабах одночасно — великі гори, середні хребти, маленькі камені, що саме і відтворюється шляхом комбінування кількох октав шуму з різною частотою ( fBm).
Яка різниця між лакунарністю та коефіцієнтом усилення в шумі fBm?
Лакунарність контролює, наскільки детальнішою стає частота з кожною доданою октавою (зазвичай подвоянням); коефіцієнт усилення визначає, наскільки слабшим є амплітуда кожної нової октави (зазвичай вдвічі зменшується). Разом вони визначають, скільки тонкої деталізації додається поверх широкого контуру, і, відповідно, наскільки рельєф буде шорстким чи гладким.
Чи дійсно моделювання гідравлічного ерозії симулює воду фізично?
Це спрощений частинно-орієнтований підхід, а не повне розв’язання рівнянь гіддинаміки: кожна крапля слідує за найкрутішим місцевим спадом і обмінюється наносниками залежно від її швидкості та здатності, без моделювання тиску чи турбулентності. Це достатньо дешево для інтерактивної роботи, при цьому все ще створюючи правдоподібні долини та відкладені форми.
Спробуйте наживо
Усе, що вище, працює прямо у вашому браузері — відкрийте Procedural Terrain і змінюйте параметри під час роботи. Нічого не встановлюється, нічого не завантажується на сервер, уся модель живе в одній вкладці.
▶ Відкрити симуляцію Procedural Terrain