Кастомні шейдери постобробки: повний цикл
Одна з частих задач у геймдеві — створити візуальний стиль, який не покривається стандартними Volume Framework. Наприклад, потрібен кастомний bloom з керованим threshold або стилізоване віньєтування. На одному мобільному проекті ми скоротили витрати на рендеринг на 25% за рахунок оптимізації шейдера з 4ms до 1.1ms — економія бюджету склала близько 30% порівняно з типовим рішенням. Ми гарантуємо, що кожен шейдер проходить профілювання на цільових пристроях і не ламає існуючі ефекти на кшталт TAA. Зв'яжіться з нами для консультації — ми підберемо оптимальний підхід.
Коли стандартних ефектів недостатньо?
Unity URP/HDRP та Unreal Engine надають Volume Framework для постобробки, але у кожного є зони, де стандартні ефекти не покривають потреби конкретного візуального стилю. В URP найчастіший біль — відсутність нативної підтримки кастомних пасів у Renderer Feature без глибокого розуміння ScriptableRenderPass та порядку виконання в RenderPassEvent. Розробники вставляють кастомний Blit в AfterRenderingPostProcessing і отримують ефект, який накладається поверх URP-івського стеку замість інтеграції всередину нього — в результаті TAA та FXAA або не працюють з кастомним матеріалом, або двоять артефакти. В HDRP ситуація інша: Custom Pass працює через CustomPassVolume, і якщо шейдер використовує _CameraDepthTexture без явного оголошення в TEXTURE2D + SAMPLER під HDRP-макросами, він просто рендерить чорний екран на деяких платформах — без попереджень у консолі. Unreal-специфіка — інша: постобробка через Material з доменом Post Process працює швидко до першого зіткнення з r.PostProcessAAQuality і тим, як TAA взаємодіє з кастомними SceneTexture нодами. Якщо шейдер читає PostProcessInput0 без урахування jitter offset, на рухомій камері з'являються ghosting, який виглядає як баг рендерера, хоча причина в шейдері.
Як уникнути ghosting при кастомних ефектах?
Ghosting виникає через неврахування jitter offset у TAA-сумісних шейдерах. При вставці кастомного паса в конвеєр необхідно явно передавати різницю між попереднім і поточним кадром. В Unity для цього використовується _ScreenParams і _Jitter у випадку URP, в Unreal — параметри з PostProcessSceneView. На етапі інтеграції ми завжди перевіряємо, чи коректно шейдер обробляє субпіксельне зміщення, і при необхідності додаємо компенсацію. Профілювання за допомогою RenderDoc і порівняння з референсним кадром дозволяють виявити такі артефакти до передачі в продакшн.
Як правильно розробити шейдер постобробки?
Покрокова інструкція:
- Аналіз референсу та постановка задачі — визначаємо, який ефект потрібен і на яких платформах.
- Прототипування в ShaderGraph або Material Editor — швидка перевірка гіпотези за 1–2 дні.
- Написання HLSL/GLSL з урахуванням платформених обмежень: для мобільних —
mediump float, мінімум семплів; для PC/консолі — multi-pass Blit та compute-шейдери.
- Інтеграція в пайплайн: ScriptableRenderPass для URP, CustomPassVolume для HDRP, Post Process Material для Unreal. Обов'язково виставляємо правильний
RenderPassEvent і перевіряємо сумісність з TAA.
- Профілювання: RenderDoc, GPU Profiler, мобільні профайлери. Оптимізуємо до цільового FPS.
На одному з проектів — мобільна RPG в URP — замовник хотів кастомний ефект «чорнильного контуру» поверх геометрії. Перший прототип через ScriptableRenderPass з Roberts Cross на depth давав 4ms на Adreno 650 при 1080p. Після переписування на single-pass зі спрощеним ядром і використанням _CameraDepthNormalsTexture замість двох окремих текстур — 1.1ms. Різниця не в алгоритмі, а в кількості текстурних фетчів. Отримайте консультацію нашого інженера — ми проаналізуємо ваш проект і запропонуємо оптимальне рішення.
Що входить у роботу
Кожен шейдер постачається з повним пакетом:
- Вихідний код шейдера (HLSL/GLSL) з коментарями
- Інтеграційний скрипт (ScriptableRenderPass / CustomPassVolume / Post Process Material)
- Інструкція з налаштування параметрів у Volume Framework
- Рекомендації щодо продуктивності для цільових платформ
- Підтримка на етапі впровадження (до 2 консультацій)
Етапи роботи над шейдером
| Етап |
Що робиться |
Орієнтовні терміни |
| Розбір референсу та ТЗ |
Аналіз візуального стилю, визначення алгоритму |
1–2 дні |
| Прототип у ShaderGraph / Material Graph |
Швидка перевірка гіпотези, погодження |
1–3 дні |
| HLSL-реалізація |
Написання шейдера під цільову платформу |
2–7 днів |
| Інтеграція в рендер-пайплайн |
ScriptableRenderPass / CustomPassVolume / PP Material |
1–3 дні |
| Профілювання та оптимізація |
Frame capture, GPU timing, оптимізація під таргет |
1–4 дні |
| Документація та передача |
Коментарі в коді, інструкція з налаштування |
0.5–1 день |
Складні ефекти з кількома пасами (наприклад, volumetric fog через ray marching у постпроцесі або screen-space subsurface scattering) можуть займати 3–4 тижні з урахуванням ітерацій.
Типові помилки при самостійній розробці
Більшість проблем — не в алгоритмі, а в інтеграції.
- Неправильний
RenderPassEvent. Вставка кастомного паса в BeforeRenderingPostProcessing без розуміння того, що URP на цьому етапі ще не застосував Color Grading — в результаті LUT накладається поверх кастомного ефекту, а не під ним.
- Ігнорування camera stacking. В URP при Overlay Camera кастомний ScriptableRenderPass, підключений до Base Camera, не виконується для Overlay — потрібно реєструвати пас в обох Renderer Asset або використовувати Universal Renderer з правильним флагом
renderingLayerMask.
- Хардкод роздільної здатності.
float2(1.0/1920.0, 1.0/1080.0) у шейдері замість _ScreenParams.zw - 1 — на пристроях з нестандартним розділенням або при dynamic resolution ефект ламається.
- Втрата HDR. Якщо ефект застосовується після tonemap, а розрахований для лінійного HDR-буфера — кольори будуть некоректні. Важливо явно визначити точку застосування в пайплайні.
Порівняння типів шейдерів за платформами
| Тип шейдера |
Mobile (Adreno 650) |
PC (RTX 3070) |
| Single-pass Blit |
<1ms |
<0.2ms |
| Multi-pass (3 Blit) |
2-3ms |
<0.5ms |
| Compute shader |
1.5-2ms |
<0.3ms |
Проконсультуйтеся з нашим інженером — ми проаналізуємо ваш проект і запропонуємо оптимальне рішення. Замовте попередню оцінку — ми розрахуємо терміни та вартість з урахуванням ваших вимог.
Як відрізнити робочий шейдер від провального?
Програміст додає в сцену воду — отримує синій прямокутник. Asset Store видає застарілий асет з артефактами на мобайлі. Розробка шейдерів — це не просто натягування текстури, а складна інженерна задача: потрібно розуміти depth buffer, семплювати нормалі в кілька шарів, організовувати foam на перетині з геометрією. Без цього шейдер або не працює, або вбиває FPS. Ми займаємося професійною розробкою шейдерів і VFX понад п’ять років — за цей час пройшли десятки проектів від інді до AAA. Одного разу замовник приніс сцену з водою з Asset Store: на мобільному пристрої вона видавала 12 FPS через відсутність LOD та неправильного batching. Переписали шейдер під URP — отримали 60 FPS зі збереженням візуалу.
URP vs HDRP: що обрати для вашого проекту?
Вибір Render Pipeline фіксується на старті — шейдери під HDRP не працюють в URP і навпаки. Оцініть компроміси за таблицею:
| Параметр |
URP |
HDRP |
| Цільові платформи |
Mobile, PC, консолі |
PC, консолі (High-end) |
| Продуктивність |
Низький overhead, до 40% швидше на мобайлі |
Високе навантаження, фотореалізм |
| Screen Space Reflections |
Обмежено (з версії URP 14) |
Повноцінно з налаштуваннями |
| Volumetric Fog |
Через кастом |
Вбудована система |
| Water System |
Відсутня |
Вбудована |
| ShaderGraph ноди |
Базовий набір |
Розширений (Diffusion Profile, Eye) |
Висновок: URP дає до +40% FPS на мобільних пристроях порівняно з HDRP. Для мобільної RPG обрали URP — на iPhone 8 отримали стабільні 60 FPS без втрати якості. HDRP виправданий на PC/консолях, де потрібен фотореалізм і вбудована Water System.
Розробка шейдерів у ShaderGraph: від води до рослинності
ShaderGraph — нодовий редактор без HLSL, але розуміння «під капотом» обов'язкове. Розберемо водний шейдер — він включає кілька технік.
Нормалі з рухом
Два шари normal map, семплованих з різними швидкостями та напрямками:
Time → Multiply (speed1) → Add → Sample Texture 2D (normalMap)
Time → Multiply (speed2) → Add → Sample Texture 2D (normalMap)
→ Normal Blend → Normal (фрагментный шейдер)
Два різнонаправлених шари створюють ефект біжучих хвиль без тайлової періодичності. Споживання — 2 texture samples, що вписується в бюджет 40 draw calls для водної поверхні.
Глибина та foam
Через нод Scene Depth (в URP/HDRP opaque texture має бути включена) отримуємо різницю між глибиною сцени та позицією фрагмента води. Мала глибина (перетин з берегом) → foam через Step/Smoothstep. Велика глибина → більш насичений синій, вища непрозорість. Foam додає 1-2 ms на GPU, але дає реалістичну берегову лінію.
Рефракція
Scene Color + зміщення UV по normal map — дно «пливе». Вода рендериться в Transparent черзі, після всієї непрозорої геометрії. Обов'язково вмикати Opaque Texture в налаштуваннях URP, інакше рефракція не працює.
Fresnel та відбиття
Fresnel Effect нод — поблизу нормалі до камери поверхня прозоріша, під гострим кутом відбиває. Фізично коректно для діелектриків. Поверх Fresnel-маски додається кубмап або Reflection Probe. На мобільних платформах Reflection Probe замінюємо на кубмап низької роздільної здатності (128x128) — економія 1-2 ms.
Шейдер рослинності
Анімація кущів та трави без фізичної симуляції — через вертексний шейдер. В ShaderGraph: беремо XZ-координати вершини як фазовий зсув, Time → Sine з різною фазою, множимо на Vertex Color канал R (білий = хитається, чорний = закріплений до землі). Результат: трава хитається хвилями, основа фіксована. Для «вітру при бігу гравця» — додаємо CPU-параметр _PlayerPosition. Такий шейдер обробляє 100 000 вершин за 0.3 ms на iPhone 11.
VFX Graph: як керувати мільйонами частинок на GPU
VFX Graph виконується повністю на GPU через Compute Shaders. На відміну від Particle System (Shuriken), яка працює на CPU, тут можна керувати мільйонами частинок без навантаження на CPU. Приклад: вибух зі шрапнеллю (200 частинок) на GPU займає 0.05 ms, тоді як CPU Particle System тієї ж складності — 0.8 ms.
Граф ділиться на контексти: Spawn (burst, constant rate, event trigger), Initialize (початкові атрибути), Update (гравітація, турбулентність, колізії), Output (Quad, Mesh, Lit/Unlit, Distortion).
Приклад: вибух зі шрапнеллю
Spawn: Single Burst (count: 200)
↓
Initialize:
Position: Sphere Volume (radius: 0.1)
Velocity: Spherical * Random(5, 15)
Size: Random(0.05, 0.3)
Lifetime: Random(0.5, 2.0)
Color: Gradient по lifetime (білий → оранжевий → сірий)
↓
Update:
Gravity (force: -9.8)
Drag (coefficient: 0.2)
Turbulence (intensity: 2.0)
Collision (SDF сцени або Depth Buffer)
↓
Output Quad (Unlit):
Texture: іскра
Blend Mode: Additive
Turbulence використовує Noise Field — тривимірний шум, частинки відхиляються органічно. Flipbook анімації в Output контексті — анімація спрайта для кожної частинки. Для мобільних платформ знижуємо кількість частинок до 50 та вимикаємо Collision — економія 3 ms.
Чому пост-обробка потребує налаштування під платформу?
Post-processing — ефекти на фінальному зображенні після основного рендеру. В Unity через Volume систему (Local/Global Volume). Типовий стек для action-проекту:
| Ефект |
Призначення |
Особливості |
| Bloom |
Світіння яскравих джерел |
Threshold 0.8, intensity 0.5 — економія 1 ms |
| Tonemapping |
ACES filmic для реалізму, Neutral для стилізації |
Стандарт для realistic проектів |
| Color Adjustments |
Контраст +10%, насиченість +5% |
Корекція під настрій |
| Vignette |
Затемнення країв |
Intensity 0.3 — фокус на центрі |
| Motion Blur |
Розмиття за вектором руху |
На мобайлі вимикаємо — -2 ms GPU |
| Depth of Field |
Боке |
У VR обережно — ламає сприйняття глибини |
| Screen Space Ambient Occlusion |
SSAO / HBAO |
Затемнення в кутах геометрії, +1.5 ms |
Для мобільних платформ ми вимикаємо Motion Blur та SSAO, знижуємо Bloom до 2-3 passes — підсумковий бюджет пост-обробки 3-4 ms. На PC/HDRP стек може займати 8-10 ms, але це компенсується потужністю GPU. Як зазначено в Unity Graphics Programming, налаштування пост-обробки під конкретний профіль GPU дає стабільний FPS без артефактів.
Що входить у роботу: від шейдера до підтримки
- Розробка кастомних шейдерів у ShaderGraph (URP / HDRP): вода, рослинність, персонажні ефекти, голограми, dissolve.
- VFX Graph ефекти: вибухи, вогонь, дим, магія, оточення. Максимальна продуктивність — до 2 млн частинок на GPU при 60 FPS.
- Налаштування та оптимізація Particle System (Shuriken) для мобільних платформ: заміна на GPU-інстанси знижує draw calls на 70%.
- Побудова Post-Processing стеку під візуальний стиль проекту з виміром часу рендеру.
- Портування шейдерів між URP та HDRP при зміні пайплайна: середній час 0.5-1 день на шейдер.
- Оптимізація VFX для цільової платформи: GPU instancing, LOD частинок, culling.
Deliverables: вихідні шейдерів та VFX графів, документація з налаштування, навчання команди (1 година консультації), підтримка протягом місяця після здачі. Оцінимо проект за 1 робочий день — зв'яжіться з нами. Отримайте консультацію щодо вашого проекту — ми підберемо оптимальне рішення та назвемо терміни.
Наш досвід та гарантії
Понад п’ять років у геймдеві, 50+ проектів (мобільні, PC, консолі). Гарантуємо, що шейдер буде працювати на цільовій платформі із заявленим FPS — якщо ні, доопрацьовуємо безкоштовно. Приклад: для однієї інді-студії переписали всі шейдери під URP — FPS на iPhone 8 зріс з 25 до 60, а бюджет часу на рендер скоротився на 40%. Використовуємо останні стабільні версії Unity (LTS) та Unreal Engine 5, працюємо з Vulkan, Metal, DirectX 12.
Порівняння: готовий асет з Asset Store часто потребує доопрацювання (сумісність, продуктивність) — кастомна розробка шейдерів обходиться в 2-3 рази швидше за часом, ніж адаптація чужого коду. А шейдер, написаний з нуля під ваші завдання, дає 100% контроль над продуктивністю та візуалом. Економія бюджету на одному проекті досягає 30% за рахунок відсутності зайвого коду.
Етапи роботи
- Аналіз: вивчаємо сцену, цільові платформи, вимоги до FPS. Фіксуємо візуальні референси.
- Прототипування: створюємо шейдер/VFX граф, тестуємо на референсному пристрої.
- Інтеграція: вбудовуємо в проект, налаштовуємо параметри, оптимізуємо draw calls та batching.
- QA: перевіряємо на всіх цільових платформах (Android, iOS, PC, консолі), виправляємо артефакти.
- Деплой та передача: віддаємо вихідні, документацію, проводимо навчання. Підтримка — 1 місяць.
Терміни: від 2 до 10 робочих днів залежно від складності. Вартість розраховується індивідуально — пишіть, оцінимо ваш проект. Замовте розробку шейдерів — отримайте готовий результат з гарантією продуктивності.