KF SDK: зоны, туман, небо и освещение
Это два урока маппера K-2 с форума killingfloor.ru (2011-2012): «KF SDK: Зоны» и «KF SDK: Освещение». Основы работы в редакторе есть в основах редактора карт и в руководстве по маппингу, а связь тумана с дистанцией отсечения разобрана в статье CullDistance и туман расстояния.
Что такое зоны
Зоны — это части игрового пространства, на которые карта делится при компиляции. Каждой зоне в редакторе можно задать свои параметры.
Чтобы увидеть зоны, переключите окно редактора в режим Zone/Portal (Alt+2): каждая зона подсвечивается своим цветом.
Как образуются зоны:
- Любое вырезанное (Subtract) пространство образует зону.
- Если одно Non-solid пространство касается другого или пересекается с ним, они образуют одну зону.
- Если Non-solid пространства не касаются друг друга, это разные зоны.
Как разделить зону порталом
Зону можно разрезать и вручную:
- Создайте плоский браш кнопкой Sheet. Размер не важен, главное, чтобы он полностью перекрывал зону в нужном месте.
- Поставьте его туда, где должна пройти граница.
- Нажмите Add Special Brush и в появившемся окне отметьте Portal, Invisible и Two Sided: перегородка будет неосязаемой, невидимой и двухсторонней. В редакторе такой браш обводится зелёным контуром.
- Скомпилируйте карту: после этого зона будет разделена.
Если перегородки мешают обзору, включите во вьюпорте Realtime Preview (клавиша P), и они станут невидимыми.
Чтобы удалить портал, выделяйте не поверхность, а сам браш, который за неё отвечает: у Zone/Portal это, как правило, зелёный каркас на 2D-видах. Тогда он удаляется клавишей Delete (уточнение K-2 из комментариев).
Настройка зон: ZoneInfo
Свойства зоне задаёт актор ZoneInfo (Actors → Info → ZoneInfo): поставьте его внутрь зоны и отредактируйте свойства. На одну зону — один ZoneInfo: если поставить в зону несколько, настройки могут работать некорректно. Через ZoneInfo можно добавить туман, полностью осветить зону и дать ей название.
Вкладка ZoneInfo:
| Свойство | Что делает |
|---|---|
bClearToFogColor | Если включён туман, скрытое им пространство окрашивается в цвет тумана |
bDistanceFog | True включает туман (туман повышает производительность) |
bSoftKillZ | Включает эффект KillZ: игрок погибает, если упадёт или поднимется на заданное расстояние по вертикали |
bTerrainZone | Обязательная опция, чтобы в зоне работал ландшафт |
KillZ | Само расстояние KillZ |
LocationName | Название локации (в KF видно только в командном чате) |
ZoneTag | Тег зоны для ZoneTrigger-ов (в KF ни опция, ни ZoneTrigger-ы не актуальны) |
Вкладка ZoneLight:
| Свойство | Что делает |
|---|---|
AmbientBrightness / AmbientHue / AmbientSaturation | Дополнительное статическое освещение всей зоны. Выглядит не очень красиво и используется редко |
bNewKFColorCorrection | Включает коррекцию цвета при включённом тумане, цвет задаётся в KFOverlayColor (используется, например, на KF-Wyre). Возможность добавила Tripwire Interactive в одном из патчей, и иногда она работает неправильно или не работает вовсе |
bNoKFColorCorrection | Не использовать коррекцию цвета |
DistanceFogBlendTime | Через сколько секунд вошедший в зону игрок увидит туман |
DistanceFogColor | Цвет тумана |
DistanceFogEnd | Расстояние от игрока, дальше которого в тумане ничего не видно |
DistanceFogEndMin | Альтернатива DistanceFogEnd для игр, где в настройках есть дальность видимости в тумане (KF к ним не относится); служит для оптимизации |
DistanceFogStart | Расстояние от игрока, на котором начинается туман. Отрицательное значение делает туман гуще |
Остальные опции (кроме KFOverlayColor) лучше оставить по умолчанию. Как подобрать начало и конец тумана под CullDistance, описано в статье CullDistance и туман расстояния.
Небо: зона SkyZoneInfo
- Создайте для неба отдельную зону — обычно это куб, вырезанный за пределами карты.
- Поставьте внутрь SkyZoneInfo (Actors → Info → ZoneInfo → SkyZoneInfo). Он служит постоянной «камерой», через которую игрок видит небо. Свойства те же, что у ZoneInfo, но у SkyZoneInfo есть направление (показано стрелкой).
- Чтобы небо не было чёрным, задайте в свойствах зоны
AmbientBrightnessили включите для окружения опцию Unlit. - Оформите скайбокс. Проще всего наложить текстуры неба на стенки куба. Можно сделать и сложнее: в скайбокс можно поставить почти что угодно (чаще всего статики), и всё это будет видно. Часто используют купол неба (Skydome) с декорациями, а анимированными текстурами делают движение облаков или молнии. Хорошие примеры — скайбоксы официальных карт KF-Suburbia, KF-Departed и KF-Wyre.
- Укажите, за какими поверхностями показывать небо. Например, если карта построена внутри огромного куба, выделите его грани, которые должны стать «прозрачными», и в свойствах поверхностей отметьте Fake Backdrop.
- Проверьте результат, включив показ бэкдропа в настройках View окна редактора (клавиша K).
Если в игре на отдельных участках карты видны размазанные «следы» текстур, так выглядит пространство за бэкдропом без скайбокса: проверьте, не отмечен ли Fake Backdrop у поверхностей, где неба быть не должно. У автора темы причиной оказался незакрытый шов в геометрии: после того как дыру закрыли, эффект пропал (K-2 и Mysterion, тема «Баг на карте с текстурами», форум killingfloor.ru).
Где взять текстуры неба и какого размера делать куб, рассказано в статье фоновые звуки, снег, телепорты и текстуры неба.
Освещение: с чего начать
Освещение — одна из важнейших частей дизайна карты. При хорошем свете скромная детализация почти незаметна, а отличную геометрию легко испортить плохим светом или Ambient-яркостью.
- Для работы со светом есть режимы вьюпорта Lighting Only (Alt+0) и Dynamic Light (Alt+5). Первый показывает освещение «в чистом виде» и является основным, во втором свет наложен на текстуры геометрии и объектов — он для доводки и полного предпросмотра.
- После добавления или изменения источников освещение надо скомпилировать. Кроме полного билда карты есть две отдельные кнопки: Build Lighting пересобирает всё освещение, Build Changed Lighting — только источники, изменённые с прошлой компиляции. Второй вариант экономит время, но игнорирует, например, изменение размера и формата карт освещения.
- Нескомпилированный свет считается динамическим и обычно не соответствует итоговому: он проходит сквозь объекты без теней, не учитываются углы падения и соседние источники.
K-2 делит освещение на три условные категории:
| Категория | Как устроено | Зачем |
|---|---|---|
| Фоновое | Свет без видимого источника: группы обычных Light-ов одинакового или близкого оттенка и насыщенности, со средним радиусом (12-32), почти равномерно распределённые по участку | Ровно осветить место без естественных источников или «расширить» их действие, имитируя рассеянный свет. Наложение похожих источников даёт много оттенков разной яркости и выглядит гораздо лучше фоновой яркости зоны |
| Естественное | Свет, который игрок связывает с видимым источником; тип любой, в том числе комбинированный, радиус зависит от карты и источника | Свет фонарей, фар, огня; сюда же относится солнечный или лунный свет под скайбокс |
| Дополнительное | В основном Light-ы с малым радиусом (2-8) и, при желании, высокой яркостью | Вместе с другими источниками подсветить детали и места, куда другой свет не достаёт, или подчеркнуть какие-то особенности |
Свойства Light
Light — обычная «лампочка», корень всех остальных типов света. Добавляется через ПКМ → Add Light Here, в браузере акторов лежит в Actor → Light.
Вкладка Light Color:
| Свойство | Что делает |
|---|---|
LightBrightness / LightHue / LightSaturation | Яркость, оттенок и насыщенность (кроме света, меняют и цвет иконки) |
Если щёлкнуть по вкладке Light Color, появятся две кнопки: взять цвет пипеткой или выбрать его на палитре. Внимание: если выделить сразу несколько источников с разными настройками, открытие палитры роняет редактор.
Вкладка Lighting:
| Свойство | Что делает |
|---|---|
bActorShadows | Отбрасывают ли акторы тени (на практике ни на что не влияет) |
bAttenByLife | Теоретически — ослабление света со временем жизни |
bCorona | Включает корону (см. ниже) |
bDirectionalCorona | Размер короны зависит от угла взгляда: максимальна при взгляде прямо и «исчезает» под углом 90 градусов |
bDynamicLight | Делает свет динамическим: он проходит сквозь объекты без теней (часто выглядит неестественно), зато не требует компиляции и годится для некоторых эффектов |
bLightingVisibility | Считать ли видимость освещения от этого источника при проверке карты |
bSpecialLit | Если True, свет виден только на поверхностях BSP-брашей с отмеченной галочкой Special Lit |
LightCone | Угол конуса света (только при LE_Spotlight); максимум 255 соответствует примерно 160 градусам |
LightEffect | Особый эффект освещения (не все работают корректно) |
LightPeriod / LightPhase | Теоретически отвечают за анимацию эффектов, но K-2 не нашёл в стандартном наборе эффекта, на который они влияли бы |
LightRadius | Радиус освещения в собственных единицах: одна единица — примерно 27 UU. Реальные границы видны, если включить отображение акторов Radii View |
LightType | Тип освещения (дополнительный эффект), работает и вместе с LightEffect, и отдельно; большинству типов нужен bDynamicLight = True |
Если на карте слишком ярко, уменьшите LightBrightness или LightRadius у источников (совет UltraKill из комментариев).
Типы источников света
Spotlight (Actor → Light → Spotlight). Направленный свет, светит конусом. По сути это обычный Light с LightEffect = LE_Spotlight, но со стрелкой направления, что упрощает настройку.
Sunlight (Actors → Light → Sunlight). Солнечный свет. От обычного Light отличается иконкой, стрелкой направления и установленным по умолчанию LE_Sunlight. Он покрывает всю территорию карты, куда может попасть. Где бы ни стоял Sunlight, источником света всегда служит пространство за бэкдропом, поэтому «небо» обязательно.
В Unreal Engine 2 нет рассеивания света как такового: солнечный свет тут как на Луне, и если Sunlight — единственный источник, всё в тени остаётся чёрным. Частично это решают дополнительные источники, в том числе дополнительные Sunlight-ы: основной Sunlight плюс несколько слабее и без оттенка, с тем же общим углом падения лучей, дают близкий к реалистичному свет на открытых пространствах. Их количество и свойства зависят от карты, и это требует возни с вкладкой Movement, точной настройки Rotation по трём осям и некоторых расчётов. Альтернатива — фоновое освещение мест в тени.
TriggerLight (Actor → Light → TriggerLight). Свет, который включается и выключается по схеме Event → Tag: в свойствах света на вкладке Events пишется тег в поле Tag, у триггера тот же тег — в поле Event. По умолчанию динамический. Для правильной работы нужно настроить InitialState:
| InitialState | Поведение |
|---|---|
TriggerTurnsOn | При активации свет включается и остаётся включённым |
TriggerTurnsOff | При активации свет выключается и остаётся выключенным |
TriggerToggle | Каждая активация включает или выключает свет, сколько угодно раз |
TriggerControl | Только для обычных Trigger-ов: свет горит, пока Trigger активирован, и наоборот |
TriggerPound | Теоретически свет должен плавно включаться и выключаться в течение RemainOnTime, на практике работает как разовый on/off |
Прочие свойства TriggerLight:
| Свойство | Что делает |
|---|---|
bDelayFullOn | Делает включение и выключение плавным, игнорируя ChangeTime |
bInitiallyOn | Включён ли свет изначально |
ChangeTime | За сколько времени яркость нарастает от 0 до заданной при включении (и наоборот при выключении) |
RemainOnTime | Теоретически параметр только для TriggerPound, на практике эффекта нет |
KFMovableLight (Actor → Light → KFMovableLight). Свет, который можно привязать к муверу, чтобы он двигался вместе с ним:
- На вкладке Lighting вручную поставьте
bDynamicLight = True. - На вкладке Movement впишите тег в поле
AttachTag. - Муверу, к которому привязываете свет, впишите тот же тег в поле
Tag(вкладка Events).
Когда мувер движется, свет повторяет то же движение относительно своей исходной позиции.
Effect_TacLightGlow и HeadlightCorona K-2 пропустил как неактуальные.
Короны
Короны света — одна из самых простых и при этом красивых декораций. По сути это видимые «скины» лампочек: спрайты с (как правило) полупрозрачной текстурой.
- В свойствах источника на вкладке Lighting поставьте
bCorona = True. - На вкладке Display задайте
Skin: выберите текстуру в браузере и нажмите Use или впишите путь вручную.
| Свойство | Что делает |
|---|---|
CoronaRotation | Коэффициент вращения короны в зависимости от расстояния от игрока до источника |
CoronaRotationOffset | Начальный поворот короны |
MaxCoronaSize / MinCoronaSize | Максимальный и минимальный размер короны |
UseOwnFinalBlend | Предположительно: используется ли сложная текстура FinalBlend |
K-2 советует делать для корон отдельные источники с нулевой яркостью и большим радиусом.
Тени и разрешение карт освещения
Качество теней прежде всего зависит от разрешения карт освещения, но это касается только BSP-геометрии.
- Выделите нужные поверхности BSP-брашей и откройте их свойства.
- Измените параметр Light map: от 256 до 1, по умолчанию 16.0. Чем меньше значение, тем выше разрешение (максимум — 1.0).
Высокое разрешение увеличивает вес карты, время компиляции и немного бьёт по производительности, поэтому 1.0-2.0 имеет смысл ставить только там, где это заметнее всего. Исключение — маленькие ненагруженные карты: на них можно сразу нажать Shift+S и выставить максимальное качество.
На полигональные модели и ландшафт свет ложится иначе (vertex lit): чем больше полигонов у модели и чем они мельче, тем лучше свет и тени (то же с сеткой ландшафта). Но до максимального качества теней на BSP всё равно далеко. Отдельные тени можно сделать Projector-ами (Actor → Projector) — они выглядят как надо на любых объектах. Главная сложность — нарисовать текстуру, ведь проектор просто проецирует её.
Формат карт освещения
Формат освещения выбирается в Build Options (параметры компиляции). Вариантов три:
| Формат | Сжатие |
|---|---|
| DXT1 | Максимальное |
| DXT3 | Среднее (используется по умолчанию) |
| RGB8 | Без сжатия |
С RGB8 освещение заметно качественнее и мягче, пропадает эффект «цветных пятен». Несжатый формат увеличивает вес карты и снижает производительность, но не так сильно, как высокое разрешение карт освещения.
Сравнивая комбинации (DXT3 или RGB8, Light map 16.0 или 1.0-2.0), K-2 пришёл к выводу: при невысоком разрешении RGB8 выглядит гораздо лучше DXT3, а при высоком разница становится очень небольшой. Искажения от сжатия намного заметнее на цветном свете, чем на белом. Подбирайте комбинацию, исходя из производительности карты.
Яркость и оттенок карты
Частая проблема: в игре яркость и общая гамма карты не совпадают с тем, что видно в редакторе, — как правило, карта получается слишком яркой. Цвет можно скорректировать в свойствах ZoneInfo для одной зоны или в Level Properties (F6) сразу для всей карты:
- На вкладке ZoneInfo поставьте
bDistanceFog = True. - На вкладке ZoneLight поставьте
bNewKFColorCorrection = True. - Отрегулируйте гамму в
KFOverlayColor. Если равномерно уменьшить все три канала B, G и R (синий, зелёный, красный), общая яркость карты снизится.
Туман обязателен для работы цветокоррекции. Если он не нужен, задайте ему запредельный радиус.
Мигалка и фары: разбор с KF-MountainPass
Из ответа K-2 в теме «Вопросы, вопросы и еще раз вопросы.» на форуме killingfloor.ru. Мигалка и фары полицейской машины на KF-MountainPass собраны из множества небольших компонентов, и лучший способ их изучить — открыть карту и посмотреть.
- Мигалка: 4 обычных Light-а, которые дают постоянный свет; 2 TriggerLight-а с
LightType=LT_BlinkиbInitiallyOn=True(bInitiallyOn— вторая строчка нижней вкладки TriggerLight); 2 спрайт-Emitter-а, генерирующие частицы вспышек. - Фары: Light-ы с нулевой яркостью и коронами; Light с малым радиусом и большой яркостью, освещающий статик на месте фар; обычные Light-ы с умеренным радиусом и яркостью, освещающие окружение.
Если свет в одной комнате освещает только стены, а в других комнатах всё в порядке, K-2 советовал проверить, освещается ли потолок, какой у источников радиус, не отмечен ли у поверхностей пола Special Lit и не шейдер ли на полу. В теме «Проблема с освещением» это оказался баг, который лечится радиусом освещения от 16 до 32 или небольшим перемещением источников.