Исходный размер 3420x4800

Результаты. Анализ шейдерных подходов и метрики производительности

Данный проект является учебной работой студента Школы дизайна или исследовательской работой преподавателя Школы дизайна. Данный проект не является коммерческим и служит образовательным целям

Ограничение области главы

Полноценные подразделы с реализациями и метриками приведены только для подходов, реализованных в рамках проекта. Подходы на основе compute-шейдеров и mesh-шейдеров в главе 3 не описываются; их теоретическое обсуждение перенесено в главу 4 (Обсуждение)

Базовая сцена

big
Исходный размер 3840x2160

Изображение базовой сцены

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

В этой сцене снег— множество отдельных белых элементов (без единой карты деформации). Специальных шейдеров деформации снега не используется. Платформа, персонаж и объекты рендерятся стандартным конвейером URP.

Loading...
Исходный размер 3008x3488

Таблица для базовой сцены

Подход на основе пиксельных (фрагментных) шейдеров

Данный подход не меняет геометрию сцены: снег по-прежнему представлен множеством отдельных. Шейдер лишь заменяет внешний вид снега во фрагментном этапе: по карте деформации (DeformMap) выполняется семплирование текстур снега и земли, смешивание и отсечение «убранного» снега (clip). Освещение — полное (основной свет, тени, дополнительные источники, specular, SampleSH)

Исходный размер 1706x957

Изображение сцены c фрагментными шейдерами

Вершинный этап (Vertex) только трансформирует позицию и передаёт UV и нормали. Геометрия остаётся той же, что и в базовой сцене — множество мешей (кусочков снега), без объединения в единую плоскость. Таким образом, пиксельный шейдер даёт визуальное при сохранении структуры сцены.

Loading...
Исходный размер 1504x1648

Таблица для пиксельного/фрагментного шейдера

Объём геометрии (Tris, Verts) близок к базовой сцене, поскольку снег по-прежнему представлен множеством элементов. Деформация без изменения геометрии — только смена и смешивание текстур во фрагменте.

Снег остаётся в виде многих кусочков; улучшается визуал. Единая глобальная текстура для всех отдельных.

Подход на основе вершинных шейдеров

Деформация снега и расчёт освещения выполняются в вершинном (Vertex) шейдере. Снег представлен в виде плоскости (plane), следы и зоны уборки реализованы за счёт карты деформации (DeformMap) и смещения вершин вдоль нормали. Как описано в работе (Hanák, 2021, Ch. 4.4)

Исходный размер 3840x2160

Изображение сцены c вершинными шейдерами

Подход переносит логику деформации в vertex stage. По карте высот (DeformMap) выполняется смещение вершин. Фрагментный этап не выполняет расчёт освещения — только отсечение «убранного» снега.

Loading...
Исходный размер 3008x3392

Таблица для вершинного шейдера

FPS выше базового за счёт упрощённого фрагментного этапа и меньшего объёма геометрии, в отличие от пиксельного шейдера, здесь снег — единая плоскость, а не много кусочков; деформация реализована через изменение геометрии (vertex displacement по DeformMap), визуально видны следы и зоны уборки, тени на снегу в данной реализации отключены намеренно для изоляции вершинного этапа.

Подход на основе тесселяции (Hull + Domain)

Деформация выполняется в Domain Shader. Hull-шейдер задаёт факторы тесселяции в зависимости от расстояния до камеры (LOD), фрагментный этап — отсечение. Снег представлен плоскостью с минимальной плотностью вершин на CPU, тесселяция увеличивает детализацию геометрии на GPU

Исходный размер 3840x2160

Изображение сцены с теселяционным шейдером

Исходная плоскость снега имеет мало вершин; Hull/Domain-шейдеры на GPU увеличивают число треугольников в зависимости от расстояния до камеры. Деформация (смещение по DeformMap) выполняется в Domain Shader, что позволяет получать плавную геометрию следов без передачи плотной сетки с CPU.

Разница в детализации плоскости снега

Loading...
Исходный размер 3008x3392

Таблица для теселяционного шейдера

Подход на основе геометрических шейдеров

Деформация снега отсутствует, геометрия повторяет базовую сцену. Геометрический шейдер формирует и модифицирует меш‑частицы падающего снега над сценой. Вершинный шейдер передаёт данные без деформации, сцена без полноценного освещения. Снег задаётся как набор mesh‑частиц

Исходный размер 3840x2160

Изображение сцены с использованием геометрического шейдера

Geometry Shader модифицирует геометрию частиц снегопада (добавляет/смещает вершины, распределяет хлопья в объёме). Три пасса — Forward, ShadowCaster, DepthOnly. Вычисления по геометрии частиц выполняются трижды за кадр.

Loading...
Исходный размер 3008x3488

Таблица для геометрического шейдера

При ином числе частиц или использовании этого шейдера метрики масштабируются с количеством снежинок.

Гибридная сцена, прямое использование шейдеров без оптимизации

Исходный размер 3840x2160

Изображение финальной сцены сцены

В конфигурации сцены, где обновление карты деформации и следы реализованы через тяжёлые операции на CPU, наблюдаются резкое падение FPS и длинные кадры

Loading...
Исходный размер 3008x3584

Таблица для гибридной сцены (без оптимизации)

Узкие места (по Profiler) — основная нагрузка на CPU. Texture2D.GetPixel (~21 ms при двух вызовах). Компоненты обновления следов активно используют чтение пикселей с CPU (GetPixel/SetPixels), что при активной ходьбе даёт суммарно десятки миллисекунд на кадр и падение FPS до ~15–20.

Несовместимость шейдера с SRP Batcher (много текстур, сложная структура CBUFFER) увеличивает overhead по SetPass и батчам.

Визуал достигнут, но производительность неприемлема без целенаправленной оптимизации.

Гибридная сцена, прямое использование шейдеров с оптимизацией

После оптимизации обновления DeformMap и состава сцены метрики существенно улучшаются

Loading...
Исходный размер 3008x3392

Таблица для гибридной сцены (с оптимизацией)

Снижена нагрузка на CPU, обновление DeformMap без тяжёлых GetPixel/SetPixels или реже вызываемые операции, при сохранении визуала.

Снег — plane, следы и детализация за счёт subdivision.

Совместимость с SRP Batcher или сокращение числа дорогих операций на CPU даёт рост FPS в несколько раз.

Что было сделано для оптимизации

  1. Одно чтение и одна запись на операцию — Раньше для каждого пикселя в круге следа могли вызывать GetPixel отдельно — при радиусе 20 это сотни вызовов на один след. Сейчас делают так: один раз читают всю карту (GetPixels ()), меняют нужные пиксели в массиве в памяти, один раз пишут обратно (SetPixels () + Apply ()). На один след или одно копание — одна пара GetPixels/SetPixels вместо сотен GetPixel
  2. Следы ставятся реже — след рисуется не каждый кадр, а только когда персонаж прошёл минимум 0.2 м или прошло не менее 0.4 с с прошлого следа, и при этом скорость выше порога. Так снижается число вызовов рисования следов в секунду
  3. Запись в текстуру только если что‑то изменилось — после расчёта круга следа проверяется наличие изменений. Если круг уже «откопан» до нужного значения — SetPixels и Apply () не вызывают. Меньше лишних записей в текстуру
  4. Опциональный путь на GPU (Compute Shader) тестировался, в итоговом варианте не использовался — в одном из компонентов можно включить использование шейдеров этого типа. Тогда обновление карты (следы, восстановление) выполняется на GPU, без GetPixels/SetPixels на CPU

В итоговом оптимизированном варианте FPS превышает не только неоптимизированную гибридную сцену, но и базовую сцену (114 FPS) — при том, что в финальной сцене присутствуют дополнительные механики, все четыре рассмотренных ранее типа шейдеров в конвейере. Таким образом, за счёт целевой оптимизации достигнут прирост производительности относительно базы даже при усложнении сцены.

Результаты. Анализ шейдерных подходов и метрики производительности
Проект создан 26.03.2026
Глава:
1
2
3
4