id: 224 slug: creating-dynamic-shadows-optimized-for-mobile-graphics title_ru: "Создание динамических теней, оптимизированных для мобильной графики" tags: [vr-ar]
Создание динамических теней, оптимизированных для мобильной графики
На мобильном GPU Shadow Map при разрешении 2048×2048 без каскадов — прямой путь к 18 мс на фреймбуфер только на теневой пасс. На Adreno 640 это съедает тепловой лимит раньше, чем отработает основная геометрия. Тени на мобиле — не «настройте и забудьте», а постоянный балансинг между визуальным качеством и термалом.
Почему стандартные настройки Unity Shadow Distance убивают производительность на мобиле
Самая распространённая ошибка — оставить Shadow Distance на значении по умолчанию (150 м) и тип теней Hard Shadows в URP без каскадного разбиения. В результате GPU рисует теневую карту для всей видимой геометрии сцены, включая объекты в 80 метрах, которые игрок никогда не разглядит достаточно близко, чтобы оценить тень.
Второй классический кейс — использование Realtime GI с Enlighten на мобиле вместе с динамическими тенями. Enlighten пересчитывает lightmap при каждом движении источника света, что на Mali-G72 с 4 ядрами превращается в постоянные дропы до 24 FPS в моменты перехода между зонами освещения. Решение — переводить все статичные объекты в Mixed Lighting с Subtractive Mode и оставлять Realtime только на персонажах.
Каскадные тени (Cascade Shadow Maps) на мобиле тоже требуют аккуратности. Два каскада вместо четырёх на дистанциях 8/40 м вместо 10/30/60/150 м дают ощутимый прирост. Shadow Bias нужно выставлять вручную под каждую сцену — автоматическое значение URP часто даёт Peter Panning на плоских поверхностях именно из-за особенностей мобильного depth buffer (16-bit на ряде устройств).
Технический стек и подходы
Работаем в Unity URP (Universal Render Pipeline) с Custom Renderer Feature для теней. Основные инструменты в процессе — Frame Debugger для анализа теневых пассов, GPU Profiler в Unity Profiler с Rendering module, и Snapdragon Profiler / Mali Graphics Debugger для захвата реальных данных с устройства.
Процесс начинается с захвата baseline: FPS, GPU time, количество Shadow Caster Draw Calls. На типичном проекте с 300+ объектами в сцене Shadow Caster Pass даёт 180–220 draw calls — это уже половина рекомендованного бюджета для мобайла (400 total).
Дальнейшая работа:
- Переводим мелкие статичные объекты (камни, бордюры, декор) в Shadow Static — они попадают в статичный Shadow Atlas и не перерисовываются каждый фрейм
- Для персонажей и динамических объектов используем Screen Space Shadows вместо Shadow Map там, где глубина сцены позволяет (работает на Vulkan/Metal)
- Настраиваем Shadow Fade Distance с плавным переходом на Blob Shadow (проецированная текстурная тень) за пределами 15 м — визуально незаметно, стоимость минимальна
- На тайловых GPU (Adreno, Mali) включаем Early-Z Culling через правильную сортировку Render Queue: непрозрачная геометрия сначала, прозрачная — в конце
Для VR-проектов на Quest 2/3 отдельная история — там используется Multiview Rendering (single-pass stereo), и Shadow Map рендерится один раз для обоих глаз. Но если в сцене есть Shadow Casting объекты с разными Culling Mask для левого/правого глаза, Shadow Pass рвётся на два независимых — сразу +8–12 мс. Это баг-ловушка, которую не видно в Editor.
Как строится работа над проектом
Аудит сцены. Собираем данные с целевого устройства через ADB + Unity Profiler: Shadow Caster Count, GPU Shadow Pass Time, тепловой троттлинг за 5 минут нагрузки.
Техническое задание. По результатам аудита определяем, что можно перевести в Baked, что оставить Mixed, какой Shadow Distance реалистичен для геймплея конкретного проекта.
Реализация. Настройка URP Asset, Renderer Feature, Culling Groups для LOD теней, написание кастомного Shadow Caster Pass если стандартный не покрывает нужды (например, для растительности с Alpha Cutout).
Тестирование на железе. Прогоняем на минимум трёх устройствах из таргетной матрицы: low-end (Snapdragon 665), mid (Snapdragon 778G), high-end (Snapdragon 8 Gen 2). Thermal throttling тест — 15 минут непрерывной игровой сессии.
Профилирование и финальная итерация. Сравниваем с baseline, при необходимости — дополнительный проход по Blob Shadow fallback.
| Масштаб задачи | Ориентировочные сроки |
|---|---|
| Аудит + базовая настройка URP (1 сцена) | 2–4 дня |
| Полная оптимизация теней (3–5 сцен) | 1–2 недели |
| VR-проект с Multiview + кастомный Renderer Feature | 2–4 недели |
Стоимость рассчитывается индивидуально после аудита проекта и анализа требований.
Типичные ошибки, которые мы видим в проектах
Не выставлен Render Shadow Maps per-object — все объекты рендерят Shadow Map независимо от расстояния до камеры, хотя дальние объекты можно убрать через ShadowCastingMode.Off на уровне LOD2.
Использование Light.shadowCustomResolution = 4096 в скрипте без проверки SystemInfo.graphicsMemorySize — на бюджетных телефонах с 2 ГБ RAM это гарантированный краш при низкой памяти.
Смешение MSAA x4 с Dynamic Shadows на одном Render Target на старых Mali — драйвер переходит в software fallback, FPS падает в 2–3 раза. На эти устройства нужно принудительно ограничивать MSAA x2 или отключать через QualitySettings.antiAliasing.





