SamuKata
teedeezet
teedeezet

boosty


Итоги месяца: сентябрь 2025

Привет всем спонсорам!
Прошёл первый полноценный месяц, проведённый в работе с новым ноутбуком. Пока всё идёт просто отлично, но минус я уже нашёл: тестировать производительность систем стало сложнее, потому что без тормозов работает любой код, который я пишу. 
[Grim Wild]
Клеточные буферы
Краткая версия: я заменил старую AoS (Array of Structures) структуру клеток уровня на SoA (Structure of Arrays), добавив поддержку двусторонней синхронизации данных с GPU для симуляций, оверлеев (режима просмотра мировой высоты, уровня освещения, крыш...) и быстрой отрисовки поверхностей. 
Подробная версия:
В старых версиях GW уровни состояли из обычного массива клеток (struct FCell). Внутри них все параметры хранились в одной большой куче: мировая высота, ID поверхности и пола, приоритет прохода, наличие крыши и блока, оттенок и интенсивность света...
У такой структуры есть несколько серьёзных проблем: 1) Допустим, мы хотим взять значения мировой высоты каждой клетки на огромном уровне. Для этого процессору приходится прыгать по полям, разбросанным в памяти далеко друг от друга. Это плохая практика. (см. картинку ниже) 2) По этой же самой причине мы не можем быстро посылать данные из/на GPU. Для совместимости приходится копировать разбросанные поля во временный массив, где все значения расположены строго друг за другом.
Новый подход у меня такой: параметры клеток теперь не хранятся в одном массиве кучей. Вместо этого, уровень содержит в себе отдельные массивы (буферы): один для всех мировых высот, другой для всех ID поверхностей, и так далее. Код становится запутаннее, зато обе проблемы, описанные выше, исчезают.
Всё, что описано выше - это "самая база". Настоящая работа начинается дальше. Объясню поставленные передо мной задачи кратко и по фактам.
Факт 1: Параметры клеток - это не только числа, а ещё и ID, а также цвета. Буферы, соответственно, тоже всё это поддерживают.
Факт 2: Видов синхронизации данных с GPU есть два: односторонние (видеокарта просто читает данные, загруженные из ОЗУ) и двусторонние (видеокарта может делать и чтение, и запись - см. главу про GPU симуляции ниже).
Пример с односторонними: Клетки, на которых стоят блоки, помечаются единицей в буфере "Wall Shadow Mask". Видеокарта читает значения и рисует на этих клетках тени, но сама редактировать данные не может.
Через одностороннюю связь также работает синхронизация ID поверхностей (для отрисовки земли, травы и прочего), крыш (чтобы солнечный свет не рисовался внутри зданий) и мировой высоты (на основании неё мы рисуем тени от поверхностей).
Интересный эффект от буферов: можно переложить задачу по генерации мировых высот клеток с CPU на GPU, чтобы значительно ускорить процесс создания планет и уровней. Дополнительных костылей для этого создавать будет не нужно, система поддерживает всё уже сейчас.
Факт 3: Буферы на стороне видеокарты представлены в виде текстур (Render Targets). Это позволит эффективно реализовать систему оверлеев (режимов просмотра температуры, воздуха, высоты клеток, скорости ходьбы, освещённости, проводки, крыш, подземных ресурсов, плодородности почв и так далее).
Факт 4: Естественно, клеточные буферы могут расширяться модами (ещё одна причина, почему старая hardcoded система нам не подходила). Классический пример про магию: мододел добавляет каждой клетке параметр "магическая аура" (то есть создаёт буфер на уровне, но это несложно - всё будет упаковано в дружелюбный интерфейс). На видеокарте его можно и читать (например, использовать для отрисовки или оверлея), и писать (аура может стать симуляцией, чтобы постепенно распространяться и изменяться).
Факт 5: Клеточные буферы имеют возможность сохраняться на диск, но это нужно не всегда. Допустим, те же "тени под блоками" мы строим с нуля при каждом заходе в игровую сессию.
Так вот, сохранённые данные - это просто одна большая строка. Соответственно, чем в ней меньше текста, тем лучше для вашего дискового пространства. Чтобы сохранения не занимали слишком много места, в будущем я введу для буферов несколько форматов сжатия. Например, можно убирать ненужную точность для чисел (сохранять "1.234" вместо "1.234567"), а ещё использовать Run-Length Encoding (вместо последовательности "1, 1, 1, 1..." записывать просто "4x1...")
Факт 6: ID поверхностей - это FName (формат хэшируемой строки из UE). А на GPU существуют только числа. Соответственно, мне надо было создать конвертацию одного в другое. То есть сказать "пусть 'Soil' будет означаться на видеокарте цифрой 1, а 'Grass' - 2..."
Я обернул этот функционал в удобный контейнер, который назвал Name Registry. Численное представление могут иметь не только ID, а ещё цвета и строки. Использоваться такая механика может и в других частях игрового процесса.
GPU Симуляции: продолжение
В сентябре я работал также над GPU симуляциями. Да, ровно как и год назад. Правда, в этот раз работа велась с совершенно другого фронта: тогда я занимался непосредственно механизмом их работы, а сейчас встраивал его в игровую логику и игровое время. То есть связывал симуляции с игровым процессом, причём так, чтобы ничего не создавало лагов.
Симуляция тепла (и воздуха, там всё аналогично) работает так: объекты поглощают или выделяют тепло, и информация об этом посылается на видеокарту в конце логического кадра. Там происходит распределение значений с учётом полученного ввода. Результат посылается обратно в ОЗУ, где встраивается в буфер (именно оттуда объекты и читают значения, например, "сколько тепла в моей клетке?").
Этот процесс не создаёт тормозов, потому что почти полностью происходит не на основном потоке игры, а на других (RenderThread и RHIThread). Если за один логический кадр (0.2 секунды без ускорения времени) прошлая симуляция не закончена, новой не начнётся. С одной стороны, это гарантирует отсутствие лагов, но с другой - может создавать задержки в распределении значений.
На схеме можно увидеть интересный принцип работы игровой логики: она вся выполняется не внутри одного кадра (создавая резкие скачки нагрузки на процессор и, как следствие, тормоза), а равномерно распределяется по временному интервалу между логическими тиками. Об этом я подробнее расскажу тогда, когда доделаю систему игрового времени.
Визуал
У поверхности травы появилась собственная текстура переходов:
А вот новые и обновлённые спрайты для птиц:
Да, я всё-таки решил оставить животным лапки! Выглядит красиво, но...
... пока не везде.
Будут ли "лапки" у людей, покажет время и мои художественные способности.
[НЕ-Публичная деятельность]
В этот раз у меня есть две новости: слабо-положительная и умеренно-отрицательная.
Начнём с позитива: вдохновение ушло от создания восьмой серии ещё дальше (но хотя бы не пропало окончательно). Вышло это особо нелепо: я просто промахнулся и кликнул не на тот документ, по итогу застряв в написании сценария для десятой серии на полдня. На этом позитив заканчивается.
Продолжается неприятная ситуация с новым роликом: вдохновение для монтажа я получить до сих пор не смог. А каждый раз, когда заставлял себя заниматься им насильно, ничего не получалось. Более того, в такие моменты я терял работоспособность во всех сферах. Из-за этого количество рабочих часов в сентябре снизилось, и я мало чего успел сделать. Придётся считать этот провал "отпуском" (довольно странным, потому что за него я не отдохнул, а устал ещё сильнее). Да, отпуск у меня, как у всех порядочных людей, тоже есть: 28 дней ежегодно.
Отторжение к монтажу - это серьёзная проблема, и я не знаю, как её исправить. Единственный вариант - это полностью уйти в текстовый блоггинг вместо Ютуба, избавив себя от того, чем я категорически не хочу заниматься.
Но пока никаких заявлений я делать не буду. Главное, что у меня есть мой любимый GW и текущие спонсоры (спасибо, что не отписываетесь даже без нового контента!). В октябре я буду просто работать (над чем именно - не так важно, главное - войти в прежний ритм), чтобы до конца года точно запустить тестирование игры со спонсорами.
Спасибо за внимание!

Итоги месяца: сентябрь 2025 Итоги месяца: сентябрь 2025 Итоги месяца: сентябрь 2025 Итоги месяца: сентябрь 2025 Итоги месяца: сентябрь 2025 Итоги месяца: сентябрь 2025

Comments

<div ><div><span class="text">> я заменил старую AoS (Array of Structures) структуру клеток уровня на SoA (Structure of Arrays), </span></div><div><span class="text">Это классическая проблема обработки больших и разнообразных данных. Не смотря на кажущуюся простоту массива структур, структура массивов(т.е. набор слоёв) почти всегда быстрее в плане обработки. Помню как к нам ещё в конце 2000-х приезжал один из разработчиков интеловской MKL(Math Kernel Library) и в том числе как раз про это говорил.</span></div><div><div class="image"><img id="44758e28-c8e3-4a06-af83-f7d8855a2453" src="https://images.boosty.to/image/44758e28-c8e3-4a06-af83-f7d8855a2453?change_time=1761837295" change_time="1761837295" width="512" height="512" style="max-width: 100%; height: auto;"></div></div>

Quark Doe

<div ><div><span class="text">В этот раз пост получился слишком техническим. Понимаю, что сейчас это читать будет интересно далеко не всем, зато в будущем текст отсюда сможет многое объяснить</span></div></div>

teedeezet


More Creators