Кастомні шейдери постобробки: повний цикл
Одна з частих задач у геймдеві — створити візуальний стиль, який не покривається стандартними 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 |
Проконсультуйтеся з нашим інженером — ми проаналізуємо ваш проект і запропонуємо оптимальне рішення. Замовте попередню оцінку — ми розрахуємо терміни та вартість з урахуванням ваших вимог.






