Это моя песня
Ход проведения Game Jam
Прошло уже 19 дней с начала нашего Game Jam, и количество поданных заявок перевалило за 200. Мы искренне поражены уровнем многих работ, и теперь совершенно очевидно, что стоило запустить подобный ивент еще полгода назад. Безоговорочно делаем это мероприятие регулярным.

Мы впервые тестируем данную систему номинаций и голосования, поэтому приходится оперативно латать дыры на ходу. Небольшие шероховатости неизбежны, но мы стараемся реагировать максимально быстро.
Прием заявок завершится в это воскресенье, после чего фавориты перейдут в стадию голосования. На этом этапе стартует ежедневный отсев: комьюнити оценивает проекты, а работа с наименьшим количеством баллов выбывает. Затем счетчик голосов сбрасывается, и процедура повторяется для оставшихся участников — и так до определения победителя.
Возможно, все это обернется полным хаосом, но мне безумно интересно посмотреть на результат.
Улучшения главного меню
На этой неделе мы внесли ряд небольших правок в интерфейс меню. Награды теперь открываются в аккуратном компактном окне вместо полноценной страницы, превью игр стали отзывчивее, а еще мы устранили баг, из-за которого меню выглядело микроскопическим на высоких разрешениях (1440p и выше). Кроме того, улучшен визуальный стиль большинства страниц.

Также мы победили неприятный баг экрана загрузки, из-за которого они накладывались друг на друга.
Улучшения лобби (Party)
Теперь максимальный размер группы увеличен с 8 до 16 человек. Помимо этого, мы переработали систему отображения статусов: теперь гораздо понятнее, что происходит, когда ваш лидер присоединяется к матчу.

Вы можете отменить подключение без выхода из группы или повторить попытку в случае сбоя. Мы также исправили проблемы со следованием за лидером при переходе между матчами, дублирующиеся приглашения и очистку соединения со Steam, добавив более понятные сообщения об ошибках.
Идентификаторы ресурсов (GUID)
Мы внедряем постоянную идентификацию ассетов, чтобы вы могли спокойно перемещать и переименовывать файлы, не опасаясь поломать ссылки.
Теперь к каждому ресурсу прилагается уникальный GUID, записанный в сопутствующем файле .meta, а любые перекрестные ссылки сохраняют этот ID наряду с путем к файлу. При загрузке система в первую очередь попытается найти ресурс по его ID, и лишь в крайнем случае вернется к последнему известному пути.
Красноречивое напоминание: обязательно включите эти .meta-файлы в вашу систему контроля версий. Если проигнорировать этот шаг, у каждого участника репозитория появятся собственные уникальные ID для одних и тех же файлов, а к хорошему это не приведет.

Это лишь первый этап масштабной работы, охватывающий базовую инфраструктуру и ссылки типов GameResource, включая значительную часть системы сцен и префабов. Ссылки из форматов Valve (например, материалы, завязанные внутри модели) пока остаются в планах.
Мы продолжим расширять поддержку, пока на этот стандарт не перейдет абсолютно все. Пока же действуйте осмотрительно и, пожалуй, не стоит прямо сейчас устраивать глобальную перестановку файлов в проекте. Мы ко всему придем.
Коротко: у ассетов появились постоянные ID, так что перенос или переименование больше не разрушают зависящие от них элементы. Главное — следите, чтобы файлы
.meta
путешествовали вместе с вашими ресурсами и попадали в репозиторий.
Скриптинг v0.1
Я добавил систему скриптов — этакий аналог Lua на базе C#. Функция экспериментальная, я буду дорабатывать ее и дальше. Это еще не финальный вариант, но вы уже можете поэкспериментировать. В комплект входит компонент ScriptControl с подсветкой синтаксиса для редактирования кода прямо на панели интерфейса игры.
Главная идея — добавить инструмент для выполнения скриптов «на лету». В будущем он станет частью Doo и существенно упростит переход с ActionGraph для многих пользователей. Также я планирую интегрировать его в редактор материалов для настройки динамических свойств через выражения.
Коротко: скриптинг уже здесь. Вы пишете код во встроенном редакторе, а изменения применяются мгновенно без необходимости пересобирать весь проект. Это отличная текстовая альтернатива визуальным нодам (ActionGraph).
Док-панели (Panel Docking)
Система интерфейса теперь обзавелась встроенным функционалом закрепления и стыковки панелей. Вы можете использовать его в собственных проектах: изменять размеры окон, перетаскивать их из одной секции в другую — словом, все работает по привычным лекалам лучших оконных менеджеров последнего десятилетия.

Мы задействуем эту механику, когда сам редактор окончательно мигрирует с Qt на панели.
Панельный редактор кривых (Panel Curve Editor)
Новый интерфейсный CurveEditor позволяет настраивать кривые точно так же, как в классическом редакторе. Хотя кого я обманываю — он даже круче.
Управление окнами в C#
Мы перенесли владение окнами игры и интерфейса в управляемый код C#. Создание, изменение размеров и рендеринг теперь функционируют рука об руку с классом PanelWindow. Туда же переехали обработка событий SDL, курсоры и подключение контроллеров.
Вместе с ними «под крыло C#» отправились горячие клавиши, настройки консоли и выполнение конфигурационных скриптов. Это позволило объединить значительную часть уровня приложения с панельным редактором и избавиться от колоссального объема дублирующегося нативного кода для работы с окнами и вводом.
Коротко: окна и обработка ввода выведены из старого нативного кода, что позволило вырезать тонны дубликатов и централизовать движок.
Пилотирование камерой
Теперь вы можете управлять камерой напрямую из вида сцены. Выберите нужную камеру, нажмите кнопку «Pilot» в окне предпросмотра и перемещайтесь привычным методом. Обзор адаптируется под настройки камеры с соотношением сторон 16:9 и сеткой по правилу третей для идеальной композиции кадра.
Эта функция незаменима при записи движений камеры в Movie Maker. Нажмите Alt+F8, чтобы начать или остановить запись прямо во время полета, а затем воспользуйтесь инструментом сглаживания (Smoothen), чтобы убрать резкие рывки. Для выхода из режима пилотирования просто нажмите Escape.
Исправления записи демок
Внутриигровая запись демок (через команду movie) стала точнее отражать происходящее на сцене. Мы добавили поддержку тумана и компонентов скайбокса, а также устранили множество багов с моделями от первого лица.
Экспорт видео после работы в Movie Maker также был оптимизирован. Новый кодировщик исключает пропуск кадров, обеспечивая идеально плавную картинку.
Анимированные спрайты в Painter
Инструмент Painter теперь умеет работать с анимированными спрайтами. Новый класс SpriteInstance отслеживает воспроизведение независимо от самого файла спрайта, позволяя без лишних танцев с бубном отрисовывать спрайты в интерфейсе и на HUD.

Быстрая настройка моделей и материалов
Создавая модель через контекстное меню в браузере ассетов, вы можете задействовать опцию Try generating materials для автоматической сборки материалов.
Редактор просканирует папку модели (и подпапки) на предмет подходящих текстурных палитр, создаст новый материал на базе выбранного шейдера и разложит текстуры по нужным слоям.
Главное условие — ваши текстуры должны следовать стростому правилу именования.
- Имена файлов должны заканчиваться на определенные суффиксы, такие как
_color,_normal,_roughи т. д. Они должны соответствовать ожиданиям шейдера (проверить это можно в редакторе материалов). - Название текстуры должно начинаться с имени соответствующего слота материала на модели. Например, если в Blender вы назвали слот материала
my_cool_material, то и текстуры для него должны стартовать с этого префикса, скажем:my_cool_material_color. Редактор поддерживает любое количество слотов и сгенерирует материал для каждого, если для модели предоставлены все необходимые текстурные наборы.
Функция работает со всеми шейдерами, включая кастомные, при условии корректного объявления ожидаемых суффиксов во входных слотах текстур (подробнее в документации по атрибутам шейдеров).
Это не замена старым методам, а альтернативный рабочий процесс для стремительного прототипирования моделей и материалов.
Дополнительные UV-каналы
Кастомные шейдеры теперь имеют доступ к третьему и четвертому UV-каналам модели через семантику вершинных входов LowPrecisionUv2 и LowPrecisionUv3.
По умолчанию в шейдере их нет — вам потребуется самостоятельно добавить их в структуру VertexInput. Вот пример интеграции UV2/UV3 поверх стандартного вершинного ввода:
VS
{
// Добавление полей для каналов UV2/UV3 поверх стандартных входных данных вершины
#include "common/vertexinput.hlsl"float2 vTexCoord3 : TEXCOORD4 < Semantic( LowPrecisionUv2 ); >;
float2 vTexCoord4 : TEXCOORD5 < Semantic( LowPrecisionUv3 ); >;
}
Также доступна страница документации со списком всей семантики вершинного ввода (и подробным разбором их назначения).
Компактные шейдеры

Мне удалось кардинально уменьшить объем и время компиляции шейдеров благодаря внедрению констант специализации Vulkan и переводу различных статических комбинаций (вариантов шейдеров) в их разряд. Это избавило нас от дублирования работы и генерации избыточного кода вариантов на этапе компиляции, при этом сохранив то же количество пайплайнов во время выполнения.
Для сложных сцен число задач компиляции пиксельных шейдеров (PS) рухнуло с 5728 до 856, а для кожи — с 512 до 128.
Это привело к колоссальному ускорению: время сборки сократилось с 6 минут до 1 минуты.
Вспомнить только времена, когда компиляция файла complex.shader занимала целых 20 часов!
Помимо сокращения комбинаций, скомпилированные шейдеры теперь хранят общие модули в единственном экземпляре на программу, а не дублируют байт-код. Модули и данные рефлексии упаковываются в общие группы, на которые ссылаются конкретные вариации.
В результате всех этих оптимизаций нам удалось драматически снизить итоговый вес поставляемых шейдеров со 129.88 МБ до 10.80 МБ.
Коротко: шейдерные фичи, меняющие только поведение (но не входы), теперь делятся скомпилированным кодом, избавляя каждый вариант от индивидуальной сборки. Это уменьшило число задач для сложных шейдеров с 5728 до 856 и радикально ускорило компиляцию.
Артефакты Bindless-рендеринга
Мы исправили пиксельные «шумы» и блочные артефакты, которые наблюдались вокруг зондов окружения (environment probes), теней и других объектов, особенно на видеокартах линейки AMD RX 6000. Проблема заключалась в том, что GPU воспринимал индекс текстуры как унифицированный (uniform), хотя разные пиксели могли запрашивать совершенно разные текстуры.

Технология Bindless позволяет шейдеру выбирать текстуру по ее индексу в большом массиве. Видеокарты выполняют вызовы шейдеров группами (waves). Если этот индекс отличается внутри группы, выборка должна быть помечена как NonUniformResourceIndex. Пропуск этой аннотации приводит к тому, что GPU берет не ту текстуру. На вашем ПК все может выглядеть идеально, а у игроков превратиться в кашу.
Теперь наш Bindless API автоматически проставляет эти аннотации на всех этапах работы шейдера.
Texture2D texture = Bindless::GetTexture2D( textureIndex );
По умолчанию мы выбираем максимальную безопасность. Но если вы абсолютно уверены, что индекс постоянен для всей группы, можно принудительно включить быстрый путь для uniform-значений. Впрочем, гарантии прироста производительности это не дает.
cbuffer DrawConstants
{
uint g_nTextureIndex;
};// Этот индекс является общим для всего вызова, поэтому используем uniform-путь.
Texture2D texture = Bindless::GetTexture2D( UniformIndex( g_nTextureIndex ) );
Выборка материалов ландшафта
Долгое время весь код семплирования текстур ландшафта был жестко зашит в стандартный шейдер террейна. Теперь мы вынесли его в общий API, благодаря чему его можно использовать практически в любых кастомных шейдерах.
Чтобы задействовать функцию, подключите terrain/TerrainCommon.hlsl в секции пиксельного шейдера (PS) и вызовите Terrain::Sample( float3 WorldPosition, bool bUseGeometricNormals ). Метод возвращает структуру Material со всеми смешанными текстурами террейна — альбедо, шероховатостью, нормалями, ambient occlusion и т. д.
Второй аргумент отвечает за использование запеченных геометрических нормалей ландшафта (по умолчанию выключено). Функция выдает точно такой же результат, какой вы видите на самом меше террейна, полностью учитывая все настройки. Именно это сейчас и использует основной шейдер ландшафта!
Я также подготовил подробную страницу документации, посвященную бэкенду террейнов. Предупреждаю: это еще не финальная версия API, и кое-что может измениться, но информации уже достаточно для написания собственных кастомных ландшафтных шейдеров.

Исправления автономного экспорта (Standalone)
На этой неделе мы уделили внимание автономным сборкам. Устранен баг, мешавший запускать экспортированные игры с кастомными иконками. Кроме того, мы начали встраивать файл проекта s&box и прочие метаданные прямо в исполняемый файл .exe, чтобы не загромождать папку ассетов.

Экспортируемые игры теперь содержат скомпилированные сборки без сопутствующих архивов исходного кода CLL и XML-документации.
Данные игры также используют корневой каталог напрямую, избегая лишних вложенных папок для каждого проекта. Спасибо пользователю boxrocket6803 за патч папки данных.
Улучшения теней
Сообщество порадовало нас крутыми патчами для теней, затрагивающими как внешний вид направленного освещения (directional shadows), так и неприятные баги рендеринга.
Мягкие тени, которые остаются мягкими
Параметр жесткости теней (Shadow Hardness) переставал оказывать какой-либо эффект на дальних каскадах направленного света. Даже при нулевой жесткости тени выглядели максимально резкими. PolEpie исправил ограничение (clamping), так что теперь контроль мягкости работает на любых дистанциях.


Перетащите ползунок, чтобы сравнить один и тот же вид при нулевой жесткости теней (Shadow Hardness 0) до и после исправления.
Более гладкие края жестких теней
Еще одно улучшение от PolEpie сглаживает «зубчатые» края жестких направленных теней при максимальном качестве фильтрации. Фильтр плавно адаптируется по мере роста жесткости, сохраняя исходную мягкость на нуле и задействуя максимум 16 сэмплов для сравнения.


Эти скриншоты до/после демонстрируют фильтрацию с учетом упомянутого выше исправления каскадов. Низкие настройки фильтрации теней и локальные источники света сохраняют прежнее поведение.
Никаких ползающих темных полос
В сценах с несколькими локальными источниками света на поверхностях могли возникать темные полосы, которые неприятно «ползали» при движении камеры. CorentArts выяснил, что причина крылась в расчете нормалей получателя тени внутри цикла освещения, где соседние пиксели могли выбирать разные ветки кода.

Теперь нормаль вычисляется до входа в цикл и передается в код теней. Кастомные шейдеры могут делать то же самое с помощью новых оверлодов явных нормалей в функциях Light::From, Light::Init и Light::Shadows. Выражаем благодарность CorentArts за фикс и всем, кто приложил примеры в исходном репорте.
Ортографические проекции
Сэм также устранил проблему с искажением экранных теней в ортографических режимах. Поскольку этот метод изначально рассчитывался на перспективную камеру, мы отключили для ортографических камер наложение масок теней.
Обновление от 26.09.15
Обновление от 26.09.08
Обновление от 26.09.01
Обновление от 26.08.19
Обновление от 26.08.05
Обновление от 26.07.22
Обновление от 26.07.15
Обновление от 26.07.08