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

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

От иммерсивных приложений до игровых миров и 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
    860
  • image_games_second_team_604_0.webp
    Разработка игры для компании Second term
    490
  • image_games_phoenix_ii_606_0.webp
    3D-анимация — тизер для игры phoenix 2.
    533

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

Финальный кадр в игровом рендере — это не то, что выходит из геометрического пайплайна. Между G-Buffer и экраном стоит стек постобработки, и именно он определяет, есть ли у картинки характер или нет. Bloom с неправильным threshold размывает хайлайты в белую кашу. Chromatic aberration с фиксированным offset выглядит как артефакт, а не стилистика. Самописный шейдер depth of field, который не учитывает CoC (circle of confusion) корректно, даёт характерную «замыленность» на границах переднего плана.

Это не абстрактные проблемы — это то, что отличает проект с нормальным визуальным стеком от проекта, где «что-то не так, но не понятно что».

Где ломается стандартный стек постобработки

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, который выглядит как баг рендерера, хотя причина в шейдере.

Что реально делается в рамках этой услуги

Разработка постпроцессингового шейдера — это не «написать 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, минимум текстурных сэмплов, отсутствие discard. PC/консоль — можно позволить fullscreen pass с несколькими Blit и compute-шейдером для separation pass в Gaussian blur.

Интеграция в пайплайн. ScriptableRenderPass для URP, CustomPassVolume для HDRP, Post Process Material для Unreal. Включая настройку Injection Point, порядка выполнения и совместимости с Motion Vectors если нужен TAA.

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

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

Этапы работы над шейдером

Этап Что делается Примерные сроки
Разбор референса и ТЗ Анализ визуального стиля, определение алгоритма 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-буфера — цвета будут некорректные. Важно явно определить точку применения в пайплайне.

Стоимость разработки рассчитывается после анализа технического задания: платформа, целевой рендер-пайплайн, сложность алгоритма и требования к производительности.