Разработка шейдеров воды и жидкостей для графики
Вода — один из самых технически насыщенных визуальных эффектов в реальном времени. Убедительный результат требует одновременной работы нескольких систем: поверхностного шейдера с fresnel, нормал-мап анимации, foam маски, vertex displacement для волн, и правильно настроенного underwater эффекта. Каждая из этих частей влияет на производительность, и баланс между визуальным качеством и frame budget — это основная инженерная задача.
Архитектура шейдера воды в ShaderGraph (URP)
В Universal Render Pipeline шейдер воды строится в ShaderGraph на базе Unlit или Lit graph в зависимости от требований к освещению. Для мобильных игр чаще Unlit с fake lighting через нормальную карту — это экономит несколько draw calls и vertex shader invocations. Для PC/console — Lit с PBR-параметрами.
Ключевые ноды и их функция в водном шейдере:
Normal Map Scrolling. Два normal map texture sample с разными UV tiling и разными направлениями scroll (через Time + UV offset нодой). Overlay или Blend Normal нода для их объединения. Это создаёт иллюзию хаотичной, живой поверхности без геометрических вычислений. Разные скорости scroll критичны — если оба texture движутся с одинаковой скоростью, паттерн становится очевидно повторяющимся через ~5 секунд.
Fresnel эффект. Fresnel Effect нода + Lerp между двумя цветами воды (глубокий и мелкий). Fresnel Exponent в диапазоне 2–5 для мягкого перехода. Для URP правильно использовать NDotL через Normal и View Direction ноды вместо упрощённого встроенного Fresnel.
Depth Fade для пены. Scene Depth нода (Eye space) минус Fragment Position даёт относительную глубину. Через Smoothstep — маска foam у береговой линии. Это один из самых дешёвых способов добавить реалистичный foam, но требует Opaque Texture включённой в URP Asset (это добавляет дополнительный blit pass, стоит учитывать).
Vertex Displacement для волн. В ShaderGraph вершинный блок: Sine нода по UV + Time с различными частотами и амплитудами для нескольких «волновых компонентов». Суммируем 2–3 волны с разными Direction векторами — получаем Gerstner wave approximation без полной физики. Важно: displacement должен быть умеренным (0.1–0.5 единицы) иначе появятся z-fighting артефакты с объектами на воде.
HDRP Water System vs custom shader
В HDRP начиная с Unity 2022 LTS есть встроенный Water System — готовый high-quality компонент с tessellation, caustics, underwater rendering и foam simulation. Если проект на HDRP и не ограничен платформой — имеет смысл использовать его как основу и кастомизировать через Water Decal и Water Mask.
Но у встроенного Water System есть ограничения: нет поддержки vertex-animated foam (только texture), Shader Graph customization ограничен специфичными Water surface shader нодами, нет возможности полного переопределения vertex shader. Для стилизованной графики (cartoon, stylized cel-shading) кастомный шейдер в ShaderGraph гибче.
Amplify Shader Editor — альтернатива ShaderGraph для проектов с legacy rendering или для команд, которые привыкли к node-based workflow, совместимому с Unity 5 стилем. Для воды в Amplify особенно удобен Grab Pass node для рефракции — в URP это требует отдельной Renderer Feature, а в Amplify это нода с параметрами.
Подводная часть и рефракция
Underwater эффект — отдельная техническая задача. Когда камера пересекает water plane, нужно: поменять post-processing (color grading + caustics + depth blur), добавить screen-space distortion, опционально — ограничить видимость fog'ом.
В URP это реализуется через Custom Renderer Feature + Volume override. Shader для подводного screen distortion: Blit Material с ShaderGraph, который применяет Time-based UV distortion к Blit Texture. Активируется через Camera overlay plane с OnTriggerEnter/Exit, который переключает Volume weights.
Рефракция воды в URP требует включения Opaque Texture. На мобильных платформах это дорого — blit всего Opaque pass для одного эффекта. Альтернатива для мобильных: fake refraction через нормальную карту с UV offset на backdrop plane, без реального grab pass.
Кейс: вода для мобильной игры
Проект: мобильная 3D-стратегия, Unity 2022 LTS, URP Mobile. Требование: море на фоне игрового поля, 60fps на mid-range Android. Ограничение: максимум 0.5ms на water shader в frame budget.
Итоговый шейдер: два scrolling normal maps (256×256 px каждый, ASTC 6x6 сжатие), Fresnel на дешёвой NDotL аппроксимации, foam через простую depth comparison без Opaque Texture (используем Depth Texture вместо Opaque Texture — она дешевле), вертексный displacement через одну Sine ноду с двумя амплитудами. Никакого reflection — только cube map на Specular. Итоговый frame cost: 0.3ms на Galaxy A53.
| Тип шейдера воды | Срок |
|---|---|
| Базовый (mobile, URP, без displacement) | 2–4 дня |
| Средний (PC/console, URP Lit, с foam и fresnel) | 4–8 дней |
| Высококачественный (HDRP или кастомный с tessellation) | 1–2 недели |
| Подводный эффект + рефракция | 3–5 дней дополнительно |
Стоимость рассчитывается после анализа платформы, рендер-пайплайна и визуальных референсов.





