Войти
ПрограммированиеФорумГрафика

Быстрое отображение множества спрайтов поверх основной сцены

Страницы: 1 2 Следующая »
#0
3:24, 14 мая 2012

Доброго времени суток!

Собственно, я продолжаю воевать с отображением карты, и сейчас возникла проблема, к которой не совсем понимаю с какой стороны подойти.
У меня рисуется карта в, грубо говоря, "основной", перспективной матрице. Поверх неё, в ортогональной проекции, рисуются всякого рода значки (GPS курсор, POI и подобная муть).  Делается это по понятным причинам - чтобы величина значков была всегда одинаковой, независимо от зума карты.
Затык встал, когда возникла потребность отобразить очень большое количество значков - около 2000. И затык в том, что тупо не хватает производительности для каждого расчитать экранные координаты (чтобы привязать значок к месту на карте) и сохранить нормальное плавное перемещение.
Вот сижу, думаю каким бы это образом оптимизировать. За любую толковую идею буду весьма признателен.

PS: OpenGL ES 1.1


#1
8:04, 14 мая 2012

Наиболее очевидное решение, возможно глупое.

1. Сделать шаг "зума" карты фиксированным и достаточно большим. К примеру таким, чтобы количество "зумов" не превышало, скажем N. Тут вам виднее каким будет N.
2. Для статичных значков просто просчитать положение заранее для каждого "зума".

3. Перемещение мобильных значков ограничить фиксированными значениями.
4. Заранее для каждого "зума", для каждого мобильного значка рассчитать величину смещения в экранных координатах.
5. Заранее для каждого "зума" рассчитать коэффициент преобразования экранных координат значка из текущего "зума" в предыдущий и следующий "зумы". Либо завести
"эталонный зум" и рассчитать коэффициент для него, для каждого другого "зума".
6. При скроллинге, для мобильных значков брать текущие координаты и умножать на соответствующий коэффициент преобразования.
7. При перемещении значка, рассчитывать его на текущем, либо "эталонном зуме".
8. Ну и очевидные вещи типа: если значок не двигался, то его не пересчитывать, поменьше вызовов функций, вместо флоатов - инты и т.п.

В общем если у нас не справляется процессор, давайте попробуем отожрать больше памяти, вдруг что-то получится.

Правка:
Хорошо, если размеры значков на разных "зумах" будут отличаться на двойку в степени, тогда в 6 пункте вместо умножений можно использовать сдвиги.

#2
8:04, 14 мая 2012

bugman
> Затык встал, когда возникла потребность отобразить очень большое количество
> значков - около 2000. И затык в том, что тупо не хватает производительности для
> каждого расчитать экранные координаты (чтобы привязать значок к месту на карте)
> и сохранить нормальное плавное перемещение.
Все значки в одной текстуре лежат, рисуешь их все за один dip ? Как координаты считаешь,
может часть расчётов можно переместить в матрицу проекции / шейдер ?

#3
12:36, 14 мая 2012

youtube
Вообще, я думал над подобной схемой, но решил поспрашивать, мож чего поумнее и изащнее посоветуют =)
К тому же, пункты 2, 4, 5 - сразу анрил, т.к. расстояние камеры до карты может быть абсолютно любым, а не только одно на каждый уровень зума.

Hybernaculum
Значки пока лежат в разных текстурах и рисую я по одному за батч, но, как я уже говорил, проблема не в рендеринге, а в переводе мировых координат в экранные - это проверено простым закомменчиванием соотв. участков кода.
Перевод координат делаю через GLUproject исходя из матриц мира.
Шейдеры юзать не могу - в 1.1 их нету, а по поводу матрицы проекции можно поподробнее?

#4
12:48, 14 мая 2012

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

#5
13:02, 14 мая 2012

Chipmunk
О, вот это уже интересно. Умножать при помощи scale или чего?

#6
13:17, 14 мая 2012

bugman
> О, вот это уже интересно. Умножать при помощи scale или чего?
Просто получить массив из 16 флоатов и прогнать умножение в цикле.

#7
13:25, 14 мая 2012

bugman
> Перевод координат делаю через GLUproject исходя из матриц мира.
а где ты взял GLUproject  для OpenGL ES 1.1 ?
>а по поводу матрицы проекции можно поподробнее?
я бы хранил координаты значков уже в мировых координатах, GLUproject  или ее аналог для OpenGL ES 1.1(кстати надеюсь не double ?) требует 2 матрицы, модельно-видовую и проекционную, внутри функции она матрицы перемножает. Напиши свой аналог функции сделай ее встраиваемой и передавай готовую перемноженную матрицу modelView * proj, ведь она не меняется от значка до значка. Для каждого значка сэкономишь на перемножении матриц, разгрузив CPU. Именно так я и сделал. У меня похожая задача, пересчет координат текста(ну символ это квадрат тот-же значок что у тебя) для 10000 точек вполне быстро работает на ARM CPU.

#8
13:26, 14 мая 2012

bugman
> а по поводу матрицы проекции можно поподробнее?
В твоём случае можно совместить преобразование из мировой системы координат в
экранные с матрицей проекции, т.е. объединить в одну матрицу, которую использовать
как матрицу проекции, и вызывать GLUproject станет больше не нужно.

#9
13:53, 14 мая 2012

Chipmunk
> Просто получить массив из 16 флоатов и прогнать умножение в цикле.
x на все 16 флоатов, потом y на все 16 флоатов...? =)

Andrey
> а где ты взял GLUproject  для OpenGL ES 1.1 ?
Взял из исходников GLU и вставил в проект =)

Andrey
> я бы хранил координаты значков уже в мировых координатах, GLUproject  или ее
> аналог для OpenGL ES 1.1(кстати надеюсь не double ?) требует 2 матрицы,
> модельно-видовую и проекционную, внутри функции она матрицы перемножает. Напиши
> свой аналог функции сделай ее встраиваемой и передавай готовую перемноженную
> матрицу modelView * proj, ведь она не меняется от значка до значка. Для каждого
> значка сэкономишь на перемножении матриц, разгрузив CPU. Именно так я и сделал.
> У меня похожая задача, пересчет координат текста(ну символ это квадрат тот-же
> значок что у тебя) для 10000 точек вполне быстро работает на ARM CPU.
Хочешь сказать, сокращение одного умножения матриц настолько в разы увеличивает перфоманс?

Hybernaculum
> В твоём случае можно совместить преобразование из мировой системы координат в
> экранные с матрицей проекции, т.е. объединить в одну матрицу, которую
> использовать
> как матрицу проекции, и вызывать GLUproject станет больше не нужно.
Не совсем понял идеи

#10
14:10, 14 мая 2012

bugman
> Хочешь сказать, сокращение одного умножения матриц настолько в разы увеличивает
> перфоманс?
ну 2000 перемножений 2 матриц. Я не гарантирую что в разы, но зачем постоянно перемножать 2 константные величины что-бы получить третью, да еще в цикле?
Ты попробуй может будет быстрее, лишнее перемножение 2 матриц сразу в глаза бросается. Можно попробовать еще отсекать значки которые перекрывают другие если это возможно
bugman
> > В твоём случае можно совместить преобразование из мировой системы координат в
> > экранные с матрицей проекции, т.е. объединить в одну матрицу, которую
> > использовать
> > как матрицу проекции, и вызывать GLUproject станет больше не нужно.
> Не совсем понял идеи
Ну по сути что и я говорил про матрицы.

#11
14:25, 14 мая 2012

Andrey
Ок, тогда давай смотреть алгоритм project'а:

1. Создаём вектор из 4 величин (x, y, z, 0).
2. Умножаем этот вектор на модельную матрицу
3. Умножаем результат на проекционную матрицу
4. Если в результате 3-я ячейка результирующего массива ненулевая, то продолжаем
5. Делаем несколько нехитрых умножений на значения из viewport и получаем результирующие координаты.

Я так понимаю, самая главная оптимизация тут - это сократить умножение на 2 матрицы до умножения на 1 матрицу, которую мы просчитываем заранее, умножая модельную матрицу на проекционную. По идее, это сделает прирост менее чем в 2 раза, т.к. одно умножение на матрицу таки останется. Как остальное оптимизировать - пока не знаю, т.к. оно всё завязано на переменных, зависящих от мировых координат.

Ты говоришь, что у тебя довольно шустро отображаются 10000 квадратов, так что наверно у тебя где-то покруче оптимизировано....

#12
15:43, 14 мая 2012

Какого рода спрайты, ты можешь показать скрин?

#13
16:08, 14 мая 2012

bugman
>4. Если в результате 3-я ячейка результирующего массива ненулевая, то продолжаем
делай проверку видимости спрайта, тогда этот пункт можно возможно пропустить, упростив функцию преобразования координат.
> шустро отображаются 10000 квадратов
Пересчет, а не отображение.

#14
16:58, 14 мая 2012

Итак, вспомнив школьную программу класса "раскрыть скобки" привёл это всё к следующему виду:

Единоразово вычисляем матрицу (при каждом изменении положения камеры мира). mm - модельная матрица мира, pm - проекционная

      tmp[0] = mm[0] * pm[0] + mm[1] * pm[4] + mm[2] * pm[8] + mm[3] * pm[12];
      tmp[1] = mm[4] * pm[0] + mm[5] * pm[4] + mm[6] * pm[8] + mm[7] * pm[12];
      tmp[2] = mm[8] * pm[0] + mm[9] * pm[4] + mm[10] * pm[8] + mm[11] * pm[12];
      tmp[3] = mm[12] * pm[0] + mm[13] * pm[4] + mm[14] * pm[8] + mm[15] * pm[12];
      tmp[4] = tmp[12] = mm[0] * pm[3] + mm[1] * pm[7] + mm[2] * pm[11] + mm[3] * pm[15];
      tmp[5] = tmp[13] = mm[4] * pm[3] + mm[5] * pm[7] + mm[6] * pm[11] + mm[7] * pm[15];
      tmp[6] = tmp[14] = mm[8] * pm[3] + mm[9] * pm[7] + mm[10] * pm[11] + mm[11] * pm[15];
      tmp[7] = tmp[15] = mm[12] * pm[3] + mm[13] * pm[7] + mm[14] * pm[11] + mm[15] * pm[15];
      tmp[8] = mm[0] * pm[1] + mm[1] * pm[5] + mm[2] * pm[9] + mm[3] * pm[13];
      tmp[9] = mm[4] * pm[1] + mm[5] * pm[5] + mm[6] * pm[9] + mm[7] * pm[13];
      tmp[10] = mm[8] * pm[1] + mm[9] * pm[5] + mm[10] * pm[9] + mm[11] * pm[13];
      tmp[11] = mm[12] * pm[1] + mm[13] * pm[5] + mm[14] * pm[9] + mm[15] * pm[13];

Вычисляем экранные x и y (z мне не нужен) для каждого спрайта. Здесь matrix - это вот та предвычисленная tmp, а result - массив, содержащий x и y:

    float a = (x * matrix[4] + y * matrix[5] + z * matrix[6] + matrix[7]);
    float b = (x * matrix[12] + y * matrix[13] + z * matrix[14] + matrix[15]);
    
    if (a == 0 || b == 0)
      return false;
    
      result[0] = ((x * matrix[0] + y * matrix[1] + z * matrix[2] + matrix[3]) / 
          a * 0.5f + 0.5f) * viewport[2] + viewport[0];
      result[1] = ((x * matrix[8] + y * matrix[9] + z * matrix[10] + matrix[11]) / 
          b * 0.5f + 0.5f) * viewport[3] + viewport[1];

Дальше пока не знаю, как оптимизировать. Если есть ещё идеи - буду рад.
В любом случае, работает уже гораздо шустрее.

Страницы: 1 2 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.