3. BASICS BATCHING LIGHTING
SHADERS
«В предыдущей серии»
Рендер, шейдеры, пост-процессинг,
etc.
<DevGamm! Minsk 2014>
• Mobile engine/tools developer в Vizor
Intreractive.
• В прошлом – программист графики
Unity3D в Steel Monkeys.
• 3 года опыта работы с графикой (Adobe
flash, DirectX, OpenGL, Metal)
• Работал с большим количеством open-
source игровых движков
5. КОГДА ОПТИМИЗИРОВАТЬ ГРАФИКУ
• «Не сейчас» (с) Сначала получите приемлемый результат.
• Когда производительность приложения на целевых
устройствах Вас не устраивает.
• Вместе с гейм-дизайнером – для решения вопросов об
игровой стилистике.
• Вместе с 2D/3D художником – для быстрой переделки
игровых ресурсов.
BASICS BATCHING LIGHTING
SHADERS
6. ФОРМАЛИЗАЦИЯ
• Что визуально изменится для игрока?
• Каковы преимущества и недостатки оптимизации?
• Какие игровые ресурсы нужно будет переделывать?
• Какой код нужно переписывать (и кто будет это делать)?
• Сколько времени займет оптимизация?
• Энтропия (Что может не заработать?).
В процессе формализации, Вы отвечаете на вопросы: «Что именно я
делаю?» и «Сколько времени это займет?»
BASICS BATCHING LIGHTING
SHADERS
7. ПРОФИЛИРОВАНИЕ
• Не считайте попугаев (FPS, draw calls), замеряйте время.
• Не замеряйте производительность в сферическом вакууме.
• Создавайте тесты для быстрого получения результатов.
• Записывайте render time, а не frame time (это исключит из
результата swap buffer delay и vSync).
• Обязательно оценивайте «до/после» только по достижении
планируемого результата.
• Получив массив результатов времени, берите медиану, а не
среднее арифметическое, иначе рискуете получить «среднюю
температуру по больнице».
BASICS BATCHING LIGHTING
SHADERS
8. ПРОФИЛИРОВАНИЕ UNITY-ПРОФАЙЛЕРОМ
• Время Camera.Render() в профайлере – это именно то, что Вам
нужно.
• Напишите простенький MonoBehaviour:
• OnPreCull() – начало фрейма
• OnPostRender() – конец фрейма
• OnGUI() – для вывода результата
BASICS BATCHING LIGHTING
SHADERS
9. General-purpose tools
• Unity profiler
• GDebugger (OpenGL
desktop)
• Microsoft PiX (DirectX 9)
• ADB GL tracer (android)
• xCode instruments (iOS)
Platform-specific tools:
• Adreno profiler (Qualcomm
Adreno)
• PerfHUD ES (NVidia Tegra)
• Mali profiler (ARM Mali)
• PVRTune (Imagination tec
PowerVR)
На личном опыте:
• Mali – самая проблемная
• Tegra – самая медленная
• PowerVR – самая
производительная
BASICS BATCHING LIGHTING
SHADERS
10. БАЗОВЫЙ ПОДХОД:
• Упрощайте шейдеры
• Упрощайте пост-процессинг
• Используйте меньше transparent-объектов
• Подключайте LOD’ы
• Используйте Material ID
• Запекайте цвет и свойства материалов в vertexColor и uv2
• Используйте native-текстуры
• Снижайте Fillrate
• Включайте оптимизацию Mesh’ей
BASICS BATCHING LIGHTING
SHADERS
11. Static batching:
(+)
• Не нужно постоянно перезаписывать VBO.
• Меньше нагрузка на CPU, так как не нужно
трансформировать вершины в runtime.
• Немного меньше matrix multiplications в runtime.
(-)
• Рендер создает физическую копию забатченной геометрии.
• Нет возможности перемещать статически забатченные
объекты.
• Для работы frustum и occlusion culling’a требуется
динамическая перезапись index buffer.
BASICS BATCHING LIGHTING
SHADERS
12. model matrix position world position
_Object2World – model matrix
_World2Object – inverse model matrix
UNITY_MATRIX_MVP – model-view-projection matrix
BASICS BATCHING LIGHTING
SHADERS
18. • Используйте как можно меньше
динамических источников
освещения на сцене
• Уменьшайте количество «per-
pixel lights в Quality Settings.
• Помечайте второстепенные
источники света как «non-
important»
• При огромном количестве
источников освещения –
подключайте Deferred shading
• Не слишком полагайтесь на
Surface шейдеры.
LIGHTING
BASICS BATCHING LIGHTING
SHADERS
23. ОПТИМИЗАЦИЯ ШЕЙДЕРНОГО КОДА
• Используйте апроксимации.
• Упрощайте математику.
• Переносите код из пиксельного шейдера в вершинный
• Не пренебрегайте интринсиками и векторизацией
• По возможности, избегайте ветвления в шейдере
• Используйте ARB_precision_hint
• При необходимости – редактируйте сгенерировнный Unity код
BASICS BATCHING LIGHTING
SHADERS
24. float x = (v1 * merge) + (v2 * (1.0 – merge));
float x = lerp(v1, v2, merge);
• Не изобретайте велосипед. Почти все уже реализовано в языке
HLSL.
• Иногда удобно использовать интринсики не по прямому
назначению.
ИНТРИНСИКИ
float4 result = dot(float4(0.3, 0.59, 0.11, 1.0), myColor);
• Не забывайте про min(), max(), abs(), mad(), и т.д.
BASICS BATCHING LIGHTING
SHADERS
25. ВЕКТОРИЗАЦИ
Я
return a.yzx * b.zxy - a.zxy * b.yzx;
return float3(
a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.z * b.y - a.y * b.z
);
• В HLSL скаляры это одномерные векторы, поэтому:
return float3(var, var, var);
• Вы можете делать swizzle в любом, удобном Вам порядке
return var.xxx;
(а вообще, это cross(a,
b))
BASICS BATCHING LIGHTING
SHADERS
26. if(x == 0)
return a;
else if(x == 1)
return b;
return lerp(a, b, floor(x));
• Постарайтесь избегать ветвления для тривиальных
случаев
• В некоторых случаях, ветвление все-таки лучше:
if(x == 0)
очень
много
кода
else if(x == 1)
clip(-1)
BRANCHING
BASICS BATCHING LIGHTING
SHADERS
27. struct VertexData {
float a : TEXCOORD0;
float b : TEXCOORD1;
float c : TEXCOORD2;
float d : TEXCOORD3;
};
myMaterial.SetFloat(„a”, 1.0f);
myMaterial.SetFloat(„b”, 2.0f);
myMaterial.SetFloat(„c”, 3.0f);
myMaterial.SetFloat(„d”, 4.0f);
struct VertexData {
float4 abcd : TEXCOORD0;
};
myMaterial.SetVector(
„abcd”,
new Vector4(1.0f, 2.0f, 3.0f, 4.0f
);
• Позволяет заменить 4 вызова glUniform1fv одним вызовом
glUniform4fv
УПАКОВКА
BASICS BATCHING LIGHTING
SHADERS
28. Вставьте этот код вместо исходного кода Вашего
шейдера
BASICS BATCHING LIGHTING
SHADERS
29. ВЫВОДЫ
• Процесс оптимизации должен быть достаточно детерминирован
• Оптимизировать можно только финальную версию игры или
модуля
• Во время оптимизации Вы снова возвращаетесь к задаче и в
процессе можете решить проблему, которая казалась
неразрешимой или была оставлена на «и так сойдет…»