• OPTIMIZATION BASICS
• BATCHING • LIGHTING • SHADERS
WORDS TO SAY
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 игровых движков
Профилирование
Анализ результатов
Проектирование
Реализация
Играбельная версия
Финальный билд
Оптимизация -циклический
процесс увеличения
производительности
BASICS BATCHING LIGHTING SHADERS
КОГДА ОПТИМИЗИРОВАТЬ ГРАФИКУ
• «Не сейчас» (с) Сначала получите приемлемый результат.
• Когда производительность приложения на целевых устройствах Вас не устраивает.
• Вместе с гейм-дизайнером – для решения вопросов об игровой стилистике.
• Вместе с 2D/3D художником – для быстрой переделки игровых ресурсов.
BASICS BATCHING LIGHTING SHADERS
ФОРМАЛИЗАЦИЯ
• Что визуально изменится для игрока?• Каковы преимущества и недостатки оптимизации?• Какие игровые ресурсы нужно будет переделывать?• Какой код нужно переписывать (и кто будет это делать)?• Сколько времени займет оптимизация?• Энтропия (Что может не заработать?).
В процессе формализации, Вы отвечаете на вопросы: «Что именно я делаю?» и «Сколько времени это займет?»
BASICS BATCHING LIGHTING SHADERS
ПРОФИЛИРОВАНИЕ
• Не считайте попугаев (FPS, draw calls), замеряйте время.• Не замеряйте производительность в сферическом вакууме.• Создавайте тесты для быстрого получения результатов.• Записывайте render time, а не frame time (это исключит из
результата swap buffer delay и vSync). • Обязательно оценивайте «до/после» только по
достижении планируемого результата.• Получив массив результатов времени, берите медиану, а
не среднее арифметическое, иначе рискуете получить «среднюю температуру по больнице».
BASICS BATCHING LIGHTING SHADERS
ПРОФИЛИРОВАНИЕ UNITY-ПРОФАЙЛЕРОМ
• Время Camera.Render() в профайлере – это именно то, что Вам нужно.
• Напишите простенький MonoBehaviour:• OnPreCull() – начало фрейма• OnPostRender() – конец фрейма• OnGUI() – для вывода результата
BASICS BATCHING LIGHTING SHADERS
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
БАЗОВЫЙ ПОДХОД:
• Упрощайте шейдеры• Упрощайте пост-процессинг• Используйте меньше transparent-объектов• Подключайте LOD’ы• Используйте Material ID• Запекайте цвет и свойства материалов в vertexColor
и uv2• Используйте native-текстуры• Снижайте Fillrate• Включайте оптимизацию Mesh’ей
BASICS BATCHING LIGHTING SHADERS
Static batching:(+)• Не нужно постоянно перезаписывать VBO.• Меньше нагрузка на CPU, так как не нужно
трансформировать вершины в runtime.• Немного меньше matrix multiplications в runtime.
(-)• Рендер создает физическую копию забатченной
геометрии.• Нет возможности перемещать статически
забатченные объекты.• Для работы frustum и occlusion culling’a требуется
динамическая перезапись index buffer.
BASICS BATCHING LIGHTING SHADERS
model matrix position world position
_Object2World – model matrix_World2Object – inverse model matrixUNITY_MATRIX_MVP – model-view-projection matrix
BASICS BATCHING LIGHTING SHADERS
BASICS BATCHING LIGHTING SHADERS
BASICS BATCHING LIGHTING SHADERS
BASICS BATCHING LIGHTING SHADERS
[0] [1] [2] [3] [4]
BASICS BATCHING LIGHTING SHADERS
BASICS BATCHING LIGHTING SHADERS
• Используйте как можно меньше динамических источников освещения на сцене
• Уменьшайте количество «per-pixel lights в Quality Settings.
• Помечайте второстепенные источники света как «non-important»
• При огромном количестве источников освещения – подключайте Deferred shading
• Не слишком полагайтесь на Surface шейдеры.
LIGHTING
BASICS BATCHING LIGHTING SHADERS
• SubShader:• Forward base
• GLES• Base
• KEYWORD_A• KEYWORD_B
...• Shadow caster• Shadow collector
• DX9• WP8• Playstation 3
…• Forward add• Prepass base• Prepass final
Shader "Custom/NewShader" { Properties { _MainTex("Base (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 200
CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex;
struct Input { float2 uv_MainTex; };
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse"}
Варианты Вашего шейдера:
BASICS BATCHING LIGHTING SHADERS
• 12K triangles• 24K vertices• 5X Blend “One
One”• 6 проходов
BASICS BATCHING LIGHTING SHADERS
BASICS BATCHING LIGHTING SHADERS
https://github.com/RChehowski/devgamm_expo
• 2K triangles• 4K vertices• 1 проход
BASICS BATCHING LIGHTING SHADERS
ОПТИМИЗАЦИЯ ШЕЙДЕРНОГО КОДА
• Используйте апроксимации.• Упрощайте математику.• Переносите код из пиксельного шейдера в вершинный• Не пренебрегайте интринсиками и векторизацией• По возможности, избегайте ветвления в шейдере• Используйте ARB_precision_hint
• При необходимости – редактируйте сгенерировнный Unity код
BASICS BATCHING LIGHTING SHADERS
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
ВЕКТОРИЗАЦИЯ
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
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
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
Вставьте этот код вместо исходного кода Вашего шейдера
BASICS BATCHING LIGHTING SHADERS
ВЫВОДЫ
• Процесс оптимизации должен быть достаточно детерминирован
• Оптимизировать можно только финальную версию игры или модуля
• Во время оптимизации Вы снова возвращаетесь к задаче и в процессе можете решить проблему, которая казалась неразрешимой или была оставлена на «и так сойдет…»
СПАСИБО ЗА ВНИМАНИЕ– Вопросы…?