Розробка шейдерів постобробки зображення ігор

Наша компанія з розробки відеоігор веде незалежні проекти, спільно з клієнтом створює ігри та надає додаткові операційні послуги. Досвід нашої команди дозволяє нам охопити всі ігрові платформи та розробити приголомшливий продукт, що відповідає баченню клієнта та перевагам гравців.

Від імерсивних застосунків до ігрових світів і 3D-сцен

Наша виділена команда для VR/AR/MR-розробки, Unity-продакшну і 3D-моделювання та анімації — з власними кейсами і презентаціями.

Відвідати персоналізований сайт
Показано 1 з 1 послугУсі 242 послуг
Розробка шейдерів постобробки зображення ігор
Складна
~5 робочих днів
Часті питання

Наші компетенції

Які етапи розробки гри?

Останні роботи

  • image_games_mortal_motors_495_0.webp
    Розробка гри для компанії Mortal Motors
    683
  • image_games_a_turnbased_strategy_game_set_in_a_fantasy_setting_with_fire_and_sword_603_0.webp
    Покрокова стратегія у фентезі сеттингу With Fire And Sword
    862
  • image_games_second_team_604_0.webp
    Розробка ігри для компанії Second term
    491
  • image_games_phoenix_ii_606_0.webp
    3D-анімація – тизер для гри phoenix 2.
    533

Розроблення шейдерів постобробки для ігор

Фінальний кадр у ігровому рендері — це не те, що виходить з геометричного pipeline. Між G-Buffer та екраном стоїть стек постобробки, і саме він визначає, чи має зображення характер чи ні. Bloom з невірним threshold розмиває highlights у білу кашу. Chromatic aberration з фіксованим offset виглядає як артефакт, а не стилізація. Самописний шейдер depth of field, який не враховує CoC (circle of confusion) коректно, дає характерну "замуленість" на межах переднього плану.

Це не абстрактні проблеми — це те, що відрізняє проект з нормальним візуальним стеком від проекту, де "щось не так, але невідомо що".

Де ломається стандартний стек постобробки

Unity URP/HDRP та Unreal Engine обидва надають Volume Framework для постобробки — але у кожного є зони, де стандартні ефекти не покривають потреби конкретного візуального стилю.

У URP найчастіша біль — відсутність нативної підтримки кастомних passes у 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, який виглядає як баг рендерера, але причина у шейдері.

Що реально робиться у рамках цієї послуги

Розроблення постпроцесингового шейдера — це не "написати HLSL". Це цикл з кількох етапів, у кожного є свої інструменти.

Аналіз візуального референсу та постановка задачі. До написання першого рядка коду — зрозуміти, що саме потрібно відтворити. Cel-shading з edge detection через Sobel на глибині та нормалях відрізняється від cel-shading через Step у освітленні. Це різні шейдери з різними trade-off по продуктивності.

Прототипування в Shader Graph / Material Editor. ShaderGraph у Unity дозволяє швидко перевірити гіпотезу без ручної компіляції. Для Unreal — Material Graph. Прототип робиться за 1–2 дні, після чого приймається рішення: залишити в нодовій системі або переписати в HLSL/Custom HLSL node для оптимізації.

Написання та оптимізація HLSL/GLSL. Фінальний шейдер пишеться з урахуванням платформи. Мобільний таргет — це mediump float, мінімум текстурних samples, відсутність discard. PC/консоль — можна дозволити fullscreen pass з кількома Blit та compute-шейдером для separation pass у Gaussian blur.

Інтеграція в pipeline. ScriptableRenderPass для URP, CustomPassVolume для HDRP, Post Process Material для Unreal. Включаючи налаштування Injection Point, порядку виконання та сумісності з Motion Vectors якщо потрібен TAA.

Профілювання. RenderDoc для frame capture, Unity Frame Debugger / Unreal RenderDoc plugin для аналізу passes. GPU Profiler для вимірювання часу конкретного pass. На мобільних — Snapdragon Profiler або Mali Graphics Debugger.

На одному з проектів — мобільна RPG у URP — замовник хотів кастомний ефект "чорнильного контуру" поверх геометрії. Перший прототип через ScriptableRenderPass з Roberts Cross на depth давав 4ms на Adreno 650 при 1080p. Після переписки на single-pass з упрощеним ядром та використанням _CameraDepthNormalsTexture замість двох окремих текстур — 1.1ms. Різниця не в алгоритмі, а в кількості текстурних fetches.

Етапи роботи над шейдером

Етап Що робиться Приблизні терміни
Розбір референсу та ТЗ Аналіз візуального стилю, визначення алгоритму 1–2 дні
Прототип у ShaderGraph / Material Graph Швидка перевірка гіпотези, узгодження 1–3 дні
HLSL-реалізація Написання шейдера під цільову платформу 2–7 днів
Інтеграція у render-pipeline ScriptableRenderPass / CustomPassVolume / PP Material 1–3 дні
Профілювання та оптимізація Frame capture, GPU timing, оптимізація під таргет 1–4 дні
Документація та передача Коментарі у коді, інструкція по налаштуванню 0.5–1 день

Складні ефекти з кількома passes (наприклад, volumetric fog через ray marching у постпроцесі або screen-space subsurface scattering) можуть займати 3–4 тижні з урахуванням ітерацій.

Типові помилки при самостійній розробці

Більшість проблем — не в алгоритмі, а в інтеграції.

Невірний RenderPassEvent. Вставка кастомного pass у BeforeRenderingPostProcessing без розуміння того, що URP на цьому етапі ще не застосував Color Grading — в результаті LUT накладається поверх кастомного ефекту, а не під ним.

Ігнорування camera stacking. У URP при Overlay Camera кастомний ScriptableRenderPass, підключений до Base Camera, не виконується для Overlay — потрібно реєструвати pass в обох Renderer Asset або використовувати Universal Renderer з правильним флагом renderingLayerMask.

Hardcode розширення. float2(1.0/1920.0, 1.0/1080.0) у шейдері замість _ScreenParams.zw - 1 — на пристроях з нестандартним розширенням або при dynamic resolution ефект ломається.

Втрата HDR. Якщо ефект застосовується після tonemap, а розраховується для лінійного HDR-буфера — кольори будуть некоректні. Важливо явно визначити точку застосування у pipeline.

Вартість розраховується після аналізу технічного завдання: платформа, цільовий render-pipeline, складність алгоритму та вимоги до продуктивності.