130 тысяч на страницу атласа 1024х1024? 3х3 пикселя куски? Из которых 8 пикселей - это бордюр? Такая себя развертка.
150к в атлас 8к у меня упаковались за 5 минут обычным и 45 секунд оптимизированным.
ncuxonaT писал: 130 тысяч на страницу атласа 1024х1024?
Я наверное неточно выразился. Куски могут быть какого угодно размера, равно как и кол-во страниц. Там какой алгоритм.
Сперва все куски сортируются по размеру
Потом выделяется страница, в которую я пытаюсь запихать вообще все куски, которые у меня есть.
Если кусок прошёл по размеру - помечаем его.
Если кусок не прошёл - ну пофик, переходим к следующему.
И так - пока не проверим абсолютно все куски.
Когда куски закончились лайтмапа считается построенной полностью.
Потому что не может быть ситуации, чтобы она не заполнилась на 100%.
Во всяком случае по разумению упаковщика.
Дальше мы переходим к следующей странице и проделываем тоже самое.
Ну и считаем, если ни один кусок не добавился - значит лайтмапы закончились, процесс завершён.
Конечно этот прогон сам по себе занимает достаточно времени, но на Кармаковском алгоритме он проходит довольно быстро.
Цитата:
ncuxonaT писал: 150к в атлас 8к у меня упаковались за 5 минут обычным и 45 секунд оптимизированным.
А что ты там оптимизировал? Я подозреваю больше всего времени отнимает выделение памяти.
Я рёбра не рендерю, чёб быстрее было. Так-то оно уберётся.
Ну вот пожалуйста. 200 тысяч кусочков на пять лайтмап 1024х1024 добавлялось полчиса, этожы ачуметь можно! Точнее даже в четыре лайтмапы, т.к. в пятой ландшафт.
Добавлено 30-11-2020 в 19:04:
Спровидливозти ради, это на работе, тут комп древний, кора дуба.
Добавлено 30-11-2020 в 19:06:
Ландшафт. Даже от провадов тени есть
Вложение: lm_0000.zip (671.9 кб)
Этот файл был скачан 150 раз.
Дядя Миша в одну большую страницу будет собираться быстрее или медленнее, чем в несколько маленьких?
Цитата:
Дядя Миша писал: А что ты там оптимизировал? Я подозреваю больше всего времени отнимает выделение памяти.
Памяти сразу много выделяю. Оптимизировал вставку нового куска. В оригинальном алгоритме идет рекурсивный поиск свободного лифа по дереву, а я завел список свободных лифов и просто по нему прохожу.
Нравится это кому-нибудь или нет, но я таки запилил простейший промежуточный бинарный формат для хранения вертексов-треугольников и назвал его CSM, что можно расшифровать как Computed Static Mesh, Compiled Static Mesh или Cached Static Mesh. Но любители конспирологии должны увидеть здесь отслыку к cs-mapping. Не будем им мешать.
И сегодня я наконец-то понял, как же мне смержить сурфейсы обратно в большие куски, не растеряв связи с группами. Причём информации придётся сохранить минимально. Нам не надо хранить информацию для каждого вертекса, нам не надо хранить информацию для каждого треугольника, нам не надо хранить информацию для каждой рендер-группы. Всё что надо сделать - это просто сохранить информацию о ректангле в специальный файлик описания шрифтов, формат которого я разработал этой весной.
Я предполагал, что мне это пригодится, поэтому формат заранее включает в себя разные типы данных: шрифты (описание букв), спрайты (центровка кадра) именованные кадры (для худ-картинок) и наконец лайтмапы.
Там можно сохранить ректангл и размер в world-units. Сами ректанглы записываются в особый файлик сопровождения шрифтов - по одному файлу на каждую лайтмапу. Каждый ректангл - это лайтгруппа. То есть когда мы грузим треугольники геометрии - мы просто напросто ищем в какой из ректанглов попал этот треугольник. Пересечение bbox и tri. В двухмерном пространстве. Задачка решается простым перебором, но здорово ускоряется при помощи AABB дерева. Или двухмерного хэша, но по памяти дерево тут быстрее. И вот таким вот образом нам не надо хранить эту информацию больше нигде. Треугольники обратно собираются в группы, используя минимум информации. Записывать координаты в лайтмапу обратно не нужно - это делается уже в BSP.
Единственный минус подхода - плотность лайтмапы можно будет отрегулировать только в BSP. Впрочем оно почти везде так. И в кутри и в сорсе. А для террейна плотность автоматически считается.
К тому же, пользователь всегда может удалить эти описания шрифтов, сделав перекомпиляцию света невозможной.
Да их бесполезно портить, компилятор их всё равно игнорит.
Дам конечно. Там оч. простой формат, вертексы, фейсы и всё.
Добавлено 02-12-2020 в 14:13:
Лиманск из Чистого Неба
И конечно машина времени, в оригинале я её так и не нашёл.
4 часа освещение считалось. Наверное из-за того, что домов слишком много. У луча много препятствий.
Добавлено 02-12-2020 в 14:16:
Следует особо отметить, что в данный момент компилятор работает по максимально негативному сценарию - каждое деревце, каждый пропс копируется и вставляется в карту заново. Из-за чего Лост-Альфовские карты, например, могут занимать до полугигабайта по размерам. Но для меня главное, что сам компилятор это выдерживает и прекрасно укладывается в 32-х битные лимиты по памяти. Уж если он такое издевательство выносит, то без дубликатов - тем более. Но это всё потом. У меня итеративная разработка.
Добавлено 02-12-2020 в 16:56:
Остались у меня две самые сложные задачи.
1. переделать механизм лайтгрупп на новую систему, о которой я написал выше. Наполовину уже сделано, т.е. bsp переписал, остался рад.
2. сделать мульти-референс модели, чтобы не дублировать геометрию. Очень много мелочей придётся учесть, это утомляет.
Опять же с коллизией вопрос в воздухе подвешен, я ею так и не занимался.
Но к счастью коллизия не затрагивает визуальную часть. Там надо будет изучить варианты. Я просто предполагаю, что если строить прямо по-хорошему конвексные хуллы, это и вправду займёт около недели. Очень тяжёлая операция.
Добавлено 02-12-2020 в 17:03:
Во, я вспомнил в чём цымес. В BSP будет введён ключ -onlylights, чтобы можно было обновлять только лампочки.
Всё что я перечислил - обязательные вещи. Без мержинга лайтмап, фпс ниже плинтуса. Без мульти-референса моделей чудовищный размер уровня, без коллизии игрок постоянно проваливается в скайбокс.
То, что про мержинг лайтмап. Я не очень понял, что с чем объединяется. Вся геометрия разбивается на лайтгруппы, которым соответствуют отдельные куски на лайтмапе, так? Потом эти лайтгруппы объединяются в большие куски, чтобы рендерить их одним дипом?
Почему нельзя хранить эти куски как субмеши с указанием номера страницы лайтмапы? И текстурные координаты для обычных текстур и для лайтмапы.
ncuxonaT писал: Я не очень понял, что с чем объединяется
Вот есть страница лайтмапы. На ней - множество мелких кусочков.
Каждый кусочек - это лайтгруппа. Это то, что удалось развернуть в единый кусок. Наверное в такой группе все треугольники соприкасаются.
Далее, большие секвенции делятся вот на такие вот маленькие. И каждая маленькая секвенция содержит набор треугольников, точно соответствующий одной лайтгруппе. Это не нужно для рендеринга. Это нужно чтобы компилятор света мог найти эти группы и посчитать свет для каждой.
Цитата:
ncuxonaT писал: Вся геометрия разбивается на лайтгруппы, которым соответствуют отдельные куски на лайтмапе, так?
да.
Цитата:
ncuxonaT писал: Потом эти лайтгруппы объединяются в большие куски, чтобы рендерить их одним дипом?
Потом нельзя - вопрос концепции. Рад не имеет права этого делать, поскольку рад по замыслу можно запускать много раз подряд. А если рад объединит сурфейсы, то второй раз его запустить будет уже нельзя.
Цитата:
ncuxonaT писал: Почему нельзя хранить эти куски как субмеши с указанием номера страницы лайтмапы?
Ну во первых оно жы там как-то разбивается на куски, чтобы в одном сабмеше было не более 65 киловертексов. А уж сколько лайтгрупп в этот меш попадёт не учитывается. При таком подходе найти какие там вертексы какой лайтгруппе соответствуют и тем более выделить эти сабмешы - достаточно ресурсоёмкая задача. Т.е. сортировка и группировка в первую очередь должны полагаться на максимально дружелюбную дату для рендинга. А не искать компромиссы, чтобы их лайтмаппер хорошо видел. Это ничем хорошим не закончится. Да и там слишком много мест, где всё это перетасовывается, я не смогу их все отследить. Можно сделать тупо - для каждого треугольника завести структурку
uint32_t numelems; // for( uint32_t i = gcontainer[container].firstelem + firstelem; i < numelems; i++ )
7
int32_t lightGroup;
8
};
9
10
// 4 bytes here
11
struct ref_group_bounds
12
{
13
hvec2 bounds; // изначальные баундсы для каждой лайтгруппы, чтобы можно было восстановить истинный
14
// размер. Места в атласе выделяются в makebsp
15
};
Это то, что мне в голову пришло в первую очередь. Но когда в сцене 4-5 миллионов сурфейсов подобные сервисные структуры могут весить до 50 мегабайт. Zhopa. Вторая мысль была озвучена выше - сохраняем для каждой страницы атласа информацию о ректанглах. А затем просто пропускаем каждый треугольник сквозь этот ректангл и находим, где он попал внутрь. Если попал - этот треугольник принадлежит этой лайтгруппе. Для ускорения процесса я построю двухмерное AABB-tree.
Полагаю это будет самый оптимальный вариант.
Есть у такого подхода и минус - невозможно сжимать в 1 пиксель совсем чёрные лайтмапы, например. Но это в целом некритично. А для лайтстилей - даже вредно.
ncuxonaT писал: Ты же в курсе, что при использовании нормалмап нормали должны быть те же самые, что были при запекании с хайполи? Или, может быть, в курсе того, что нормали не завязаны на геометрию и могут быть произвольно отредактированы? Например, для волос или веток деревьев нормали часто проецируют со сферы.
А можно для дебилов как сделать так же красиво? А то у меня пока как слева деревья выходят.
Дядя Миша лайтгруппы нужны только раду? Но развертку под лайтмапу создает бсп?
Raid скрипты slide normal thief или noors normal thief для 3дмакса проецируют и переносят нормали с одного объекта на другой. Создаешь вокруг дерева сферу или полусферу, выбираешь её как источник нормалей, крону дерева выбираешь как таргет и переносишь. https://gamebanana.com/tuts/12231