Skip to content

Repository files navigation

ProceduralGeneration

Дипломная работа: процедурная генерация ландшафта в реальном времени на Unreal Engine 5.1. Код написан в 2023 году и с тех пор не развивался — я оставляю его как есть, потому что он показывает работу с алгоритмами шума, а не мой сегодняшний подход к архитектуре.

Что здесь есть

Актор AGenerator строит сетку TileCount x TileCount через UProceduralMeshComponent и задаёт высоту вершин функцией шума. Сетка перестраивается вокруг игрока, когда он отходит от её центра дальше чем на четверть размера.

Реализованы вручную, без использования FMath::PerlinNoise:

  • шум Перлина на таблице перестановок с интерполяцией по кривой 6x^5 - 15x^4 + 10x^3;
  • двумерный симплекс-шум (скос координат, три угла симплекса, градиенты по хешу);
  • фрактальное суммирование октав с настраиваемыми Lacunarity и Persistence;
  • набор вспомогательных шумов для сравнения: белый, синус-косинус, плоский.

Параметры шума вынесены в FNoiseInfo и настраиваются из редактора, результат виден сразу через OnConstruction.

Что я переделал бы сейчас

Список писал заново, перечитав собственный код:

  1. Генерация в игровом потоке. Перестроение сетки происходит синхронно в Tick, отсюда фризы при пересечении границы. Расчёт вершин параллелится тривиально (ParallelFor по строкам), готовка коллизии выносится через bUseAsyncCooking.
  2. Четырёхкратный пересчёт шума. Цикл идёт по клеткам и считает высоту всех четырёх углов, хотя углы общие у соседних клеток. Нужно два прохода: сначала вершины и UV по сетке (TileCount + 1)^2, потом индексы треугольников.
  3. Нормали. Считается одна нормаль на клетку и присваивается трём вершинам, соседние клетки её перезаписывают — освещение ложится гранями. Правильно накапливать нормали по всем смежным треугольникам и нормализовать в конце. Тангенты не заполняются вообще, поэтому нормал-мапы в материале работать не будут.
  4. Пересоздание секции меша. Топология не меняется, меняются только позиции вершин, так что после первого раза достаточно UpdateMeshSection вместо CreateMeshSection. Плюс лишний AttachToComponent при каждой перегенерации.
  5. Одна плитка вместо чанков. Сейчас это один меш, который телепортируется за игроком. Нормальное решение — сетка чанков с кешем, догрузкой соседей заранее и LOD по расстоянию.
  6. Архитектура. Вся ответственность в одном акторе: и данные, и генерация, и отрисовка. Расчёт высот — чистая функция, ему нечего делать в AActor; я бы вынес его в отдельный класс без зависимости от движка, а актор оставил бы тонким слоем представления. Выбор шума через switch и указатель на функцию заменил бы на стратегию.
  7. Детерминированность. WhiteNoise использует FMath::RandRange, то есть не воспроизводится от сида. Для мультиплеера или сохранений это ломает всё: сид должен полностью определять результат.
  8. Мелочи стиля UE. Перечисление без префикса E, поля публичные вместо UPROPERTY с доступом через геттеры, таблица перестановок как int32[512] вместо uint8[512], отладочный вывод в релизном пути.

Сборка

Unreal Engine 5.1, модуль ProceduralMeshComponent подключается в Build.cs.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages