Оптимизация для Android и iOS устройств

Раздел, посвящённый самому важному - скорости.

Re: Оптимизация для Android и iOS устройств

Сообщение gnoblin 17 апр 2012, 17:33

Belfegnar_ писал(а):60 на 70 пикселей (для разрешения 540х960), анимация заключается в изменении uv вершин, текстура - атлас из таких 60х70 изображений, процентов 80 текстуры - полностью прозрачные.


я бы спрайты обрезал в 3д пакете (на каждый кадр - свой мешик)
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Оптимизация для Android и iOS устройств

Сообщение Battle Angel Alita 17 апр 2012, 17:53

>60 на 70 пикселей (для разрешения 540х960)
>2000 "спрайтов"

60 * 70 * 2000 = 8400000 пикселей
960 * 540 = 518400 пикселей
овердро - 16.2
Может стоит сменить концепцию с "300 спартанцев" на "3 спартанца"?

Ну а так - делаем хитрый меш на 2000 спрайтов, считаем положение на экране, UV координаты и анимируем на GPU, если спрайты двигаются по сложной траектории - двигаем на CPU, если по простой - двигаем на GPU. Можно перераспределять нагрузку в зависимости от мощности GPU/CPU.
Мозг рака
Изображение
Аватара пользователя
Battle Angel Alita
UNIверсал
 
Сообщения: 476
Зарегистрирован: 25 ноя 2009, 14:52

Re: Оптимизация для Android и iOS устройств

Сообщение gnoblin 17 апр 2012, 18:48

есть же динамик бачинг (и, по-ходу устаревший, sprite manager)
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Оптимизация для Android и iOS устройств

Сообщение Belfegnar_ 17 апр 2012, 20:26

gnoblin писал(а):я бы спрайты обрезал в 3д пакете (на каждый кадр - свой мешик)

Мне кажется, что 8000 анимированных вершин в кадре и так многовато. Вариант конечно, но будет ли такой большой выигрыш.
есть же динамик бачинг (и, по-ходу устаревший, sprite manager)

Проводил много тестов. И мои тесты показали, что меш из 4000 вершин (массив вершин редактируется каждые 0.033 секунды) выдает больше фпс, чем 1000 четырехвершинных спрайта (Sprite manager не пробовал, мне показалось там много лишнего).
Ну а так - делаем хитрый меш на 2000 спрайтов, считаем положение на экране, UV координаты и анимируем на GPU, если спрайты двигаются по сложной траектории - двигаем на CPU, если по простой - двигаем на GPU. Можно перераспределять нагрузку в зависимости от мощности GPU/CPU.

Насчет расчетов на ГПУ.. Мысли были, но на реализацию пока не хватило умишка. А как данные (позиция, направление, анимация) в шейдер передавать? Через текстуру, цвет вершин?
Belfegnar_
UNIт
 
Сообщения: 112
Зарегистрирован: 22 ноя 2010, 14:08

Re: Оптимизация для Android и iOS устройств

Сообщение Fredo 17 апр 2012, 20:29

Battle Angel Alita писал(а):>60 на 70 пикселей (для разрешения 540х960)
>2000 "спрайтов"

60 * 70 * 2000 = 8400000 пикселей
960 * 540 = 518400 пикселей
овердро - 16.2
Может стоит сменить концепцию с "300 спартанцев" на "3 спартанца"?

Ну а так - делаем хитрый меш на 2000 спрайтов, считаем положение на экране, UV координаты и анимируем на GPU, если спрайты двигаются по сложной траектории - двигаем на CPU, если по простой - двигаем на GPU. Можно перераспределять нагрузку в зависимости от мощности GPU/CPU.

Хотелось бы уточнить, translate двигает cpu'ом, а gpu'ом вертекс шейдер? Если я все правильно понимаю, то я не пойму зачем двигать gpu, ведь коллайдер от перемещения вертексов не сдвинется О_О. Объясните пожалуйста.
Аватара пользователя
Fredo
UNITрон
 
Сообщения: 213
Зарегистрирован: 06 янв 2011, 05:37

Re: Оптимизация для Android и iOS устройств

Сообщение Belfegnar_ 17 апр 2012, 20:55

никаких коллайдеров в таких масштабах, боже упаси)))
Есть логическая единица - спрайт/юнит. Он хранит свою позицию, скорость и позицию, в которую ему нужно переместиться. Используя эти данные мы передаем в шейдер каким-то образом вектор движения вершин, относящихся к этому спрайту. Шейдер их двигает. Движения самого спрайта при этом не происходит, происходит "скачек" в целевую позицию через рассчитанное время (с помощью корутины, например), которое спрайт затратил бы на движение. Обнуляем вектор движения вершин, шейдер больше их не двигает.
Вот такого эффекта я пытаюсь добиться. Может есть более эффективный путь?
Belfegnar_
UNIт
 
Сообщения: 112
Зарегистрирован: 22 ноя 2010, 14:08

Re: Оптимизация для Android и iOS устройств

Сообщение PaXLiCh 17 апр 2012, 21:06

Перемещение спрайта по сцене одиним только вершинным шейдером? а это точно выгодно? для всех девайсов оно будет полезным? не задохнется какой-нибудь PowerVR от обилия пересылаемых на него векторов?
всем привет, кто помнит blitz.pp.ru
PaXLiCh
UNец
 
Сообщения: 19
Зарегистрирован: 12 авг 2011, 12:22

Re: Оптимизация для Android и iOS устройств

Сообщение Battle Angel Alita 17 апр 2012, 21:14

>А как данные (позиция, направление, анимация) в шейдер передавать? Через текстуру, цвет вершин?
Через неиспользуемые атрибуты - цвет, нормаль, UV-координаты.
Статья по теме: http://www.gamedev.ru/pages/blackangel/articles/?id=1

>не задохнется какой-нибудь PowerVR от обилия пересылаемых на него векторов?
8000 вершин не так много.
Mali может задохнуться т.к. у него 1 вертексный блок на 4 пиксельных.
Надо писать и тестить.
Мозг рака
Изображение
Аватара пользователя
Battle Angel Alita
UNIверсал
 
Сообщения: 476
Зарегистрирован: 25 ноя 2009, 14:52

Re: Оптимизация для Android и iOS устройств

Сообщение Belfegnar_ 18 апр 2012, 19:41


Очень любопытная статья. Похоже раритет.
Однако особой необходимости в движении шейдером я пока не вижу (хотя все равно пилю в этом направлении), ну разве что освободить проц под какие-то серьезные расчеты.
Продолжил свои тесты.. В итоге все-таки упираюсь в альфу
2000 плашек, 5 анимаций по 3 кадра каждая
1) шейдер UnlitAlpha с вики 30-45fps
Скрытый текст:
2012-04-18_20-08-37.jpg

2) шейдер Mobile/Particles/AlphaBlended 55-60fps (+придется заморачиваться с сортировкой)
Скрытый текст:
2012-04-18_20-11-11.jpg

3) ну и для сравнения Mobile/VertexLit 60+ fps
Скрытый текст:
2012-04-18_20-21-21.jpg

ЧЯДНТ? Может быть есть где-то скиптик создающий меш по изображению? Я бы экспериметнул с мешем по контуру
П.С. Оказывается самая "тяжелая" часть работя с мешем, это передача в него цвета вершин..
Скрытый текст:
П.П.С. 16000 плашек в меше (64000 вершин) обновляется несколько раз в секунду на CPU
HTML код для вашего блога :
Код: Выделить всё
<script language='javascript' type="text/javascript"> document.write("<iframe marginheight='0' src='http://unity3d.ru/distribution/player.php?url=http://dl.dropbox.com/u/74221763/WebPlayer.unity3d&w=1024&h=768&t=true&preview=1' height='"+(768+30)+"' width='1024' frameborder='0' scrolling='no'></iframe>"); </script>
У вас нет доступа для просмотра вложений в этом сообщении.
Belfegnar_
UNIт
 
Сообщения: 112
Зарегистрирован: 22 ноя 2010, 14:08

Re: Оптимизация для Android и iOS устройств

Сообщение Battle Angel Alita 18 апр 2012, 20:32

>В итоге все-таки упираюсь в альфу
Можно попробовать premultiplied alpha

>Оказывается самая "тяжелая" часть работя с мешем, это передача в него цвета вершин..
Интересно, как юнька хранит меш в памяти - vnc.vnc.vnc или vvv.nnn.ccc (vertex, normal, color)??
Если первый то так скакать по памяти будет конечно медленно.
Не проблема, можно через текстуру передавать, она в памяти линейно лежит.
Мозг рака
Изображение
Аватара пользователя
Battle Angel Alita
UNIверсал
 
Сообщения: 476
Зарегистрирован: 25 ноя 2009, 14:52

Re: Оптимизация для Android и iOS устройств

Сообщение Belfegnar_ 30 апр 2012, 04:27

Battle Angel Alita писал(а):Можно попробовать premultiplied alpha

оно?
Синтаксис:
Используется glsl
Shader "Particles/Alpha Blended Premultiply" {
Properties {
    _MainTex ("Particle Texture", 2D) = "white" {}
}

Category {
    Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
    Blend One OneMinusSrcAlpha
    ColorMask RGB
    Cull Off Lighting Off ZWrite Off Fog {Mode Off}

    BindChannels {
        Bind "Color", color
        Bind "Vertex", vertex
        Bind "TexCoord", texcoord
    }

    // ---- Dual texture cards
    SubShader {
        Pass {
            SetTexture [_MainTex] {
                combine primary * primary alpha
            }
            SetTexture [_MainTex] {
                combine previous * texture
            }
        }
    }

    // ---- Single texture cards (not entirely correct)
    SubShader {
        Pass {
            SetTexture [_MainTex] {
                combine texture * primary
            }
        }
    }
}
}

Что ему еще можно причесать для мобилки? Правильно ли я понял, что текстура должна быть специальным образом подготовлена?
Не проблема, можно через текстуру передавать, она в памяти линейно лежит.

Тут такое дело, даже если и получится небезопасным кодом напрямую в память писать цвета текстуры (обойдя таким образом медленный SetPixel), чтобы заслать ее в видеокарту, надо Apply() вызывать. А это тоже как-то не быстро.
Наваял тут свой варант "анимирующего шейдера". Прошу пинать в нужном направлении. Но не сильно, это мой второй опыт общения с шейдырами (в первый раз это была замена Queue у UnlitAlpha :D )
Использую нормаль как вектор направления движения
tangent.x - время начала движения
tangent.y - скорость анимации (время на кадр)
tangent.z - ширина кадра анимации

Синтаксис:
Используется glsl
Shader "Custom/AgentsAnimator" {
Properties {
    _MainTex ("Texture", 2D) = "white" { }
        _Speed ("Speed", Float) = 1
}

SubShader {
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
    Pass {

CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

float _Speed;
sampler2D _MainTex;

struct appdata {
    float4 vertex : POSITION;
        float3 normal : NORMAL;
    float2 texcoord : TEXCOORD0;
        float4 tangent : TANGENT;
};

struct v2f {
    float4 pos : POSITION;
    float2 uv : TEXCOORD0;
};

float4 _MainTex_ST;

v2f vert (appdata v)
{
    v2f o;

  float4  pos;
  int maxFrames = 3;
  float fps = v.tangent.y;
 
  float spriteTime = _Time.y - v.tangent.x;
  pos.xyz = v.vertex.xyz + v.normal * spriteTime * _Speed;
  pos.w = 1.0f;  
  o.pos = mul(UNITY_MATRIX_MVP, pos);

  int curFrame = (int)(abs(cos(spriteTime/fps))*maxFrames);
  float2 tex = float2(v.texcoord.x + curFrame* v.tangent.z, v.texcoord.y);
  o.uv = TRANSFORM_TEX (tex, _MainTex);

  return o;
}

half4 frag (v2f i) : COLOR
{
    return tex2D (_MainTex, i.uv);
}
ENDCG

    }
}
Fallback "VertexLit"
}

теоретически выигрываем на перемещении спрайта, обращаемся к видеокарте (создаем vbo) только в момент начала движения. Но фактически, когда спрайтов много и все стартуют в разное время, периодически меняя направление, число обращений такое же как и без шейдера, когда все на CPU)) Экономия за счет того, что Lerp на CPU не делаем?
П.С. Опа. Только что заметил, что "предсказанное" на CPU время движения не совпадает с фактическим временем перемещения спрайта на GPU, в результате чего в конце происходит небольшой скачек
Belfegnar_
UNIт
 
Сообщения: 112
Зарегистрирован: 22 ноя 2010, 14:08

Пред.

Вернуться в Оптимизация

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6