В браузере лучше всего использовать одну огромную таблицу спрайтов или много (10000) разных PNG?


33

Я создаю игру в jQuery, где я использую около 10000 плиток 32x32. До сих пор я использовал их все по отдельности (без спрайт-листа). Средняя карта использует около 2000 плиток (иногда повторно используемые PNG, но все отдельные div), а производительность варьируется от стабильной (Chrome) до немного запаздывающей (Firefox). Каждый из этих элементов позиционируется абсолютно с использованием CSS. Их не нужно обновлять каждый тик, только когда загружается новая карта.

Будет ли для производительности лучше использовать методы spritesheet для элементов div, использующих CSS-позиционирование фона, как это делает gameQuery?

Заранее спасибо!


3
Где, черт возьми, вам нужно 10 000 плиток для карты? Я предлагаю вам не загружать / рисовать всю карту на стороне пользователя. Показать только часть, которая видна. Когда пользователь переместится, загрузите следующий раздел. Как работает каждая 3D графика.
— Deele

Средняя карта использует 2000 различных плиток или всего 2000 плиток? Насколько велики карты, которые вы создаете?
— Ник Ларсен

Рассматривали ли вы использование одного или нескольких больших изображений в качестве фона и выполнение полигонального обнаружения столкновений для границ?
— SAHornickel

Ответы:


50

Мое предложение

Слишком много небольших PNG-файлов приведет к большим накладным расходам в сети (из-за размера HTTP-запросов, но также и из-за заголовка PNG и, что еще важнее, из-за невозможности эффективного сжатия). С другой стороны, один очень большой PNG имеет недостатки, которые требуют некоторого времени для загрузки, и он должен постоянно находиться в памяти (40 мегабайт на 10 000 плиток) в непрерывном куске памяти.

Я рекомендую золотую середину: несколько PNG разумного размера, например, 1024 плитки размером 32 × 32 . Может быть сгруппированы по темам (например, PNG с лесными плитками, одна с горными плитками, другая с городскими плитками - я не знаю тему вашей игры, но вы поняли идею).

Замечание об эффективности кеша

Из-за эффективности доступа к памяти, вы никогда не должны делать свои спрайт-листы слишком широкими. Блики плитки из изображения 128 × 8192 всегда будут быстрее, чем блики из изображения 8192 × 128.

Представьте, что вы хотите скопировать первую плитку на изображении размером 8192 × 128. Для простоты предположим, что 1 пиксель равен 1 байту. Первые две строки пикселей расположены таким образом (ячейки содержат номер байта в памяти):

┌────┬────┬───┬────┬──────────┬─────┐
│  0 │  1 │...│ 31 │   ....   │ 8191│ 1st line of pixels: bytes 0 to 8191
├────┼────┼───┼────┼──────────┼─────┤
│8192│8193│...│8223│   ....   │16383│ 2nd line of pixels: bytes 8192 to 16383
├────┼────┼───┼────┼──────────┼─────┤
│ .. │ .. │...│ .. │   ....   │ ... │

Таким образом, чтобы убрать первую строку первого заголовка, механизм браузера будет извлекать байты 0в31 . Для блитирования на вторую линию , она будет получать байты 8192к8223 , и так далее до 32 - й линии , где байтов 253952для253983 извлекаются.

Общее количество обработанных байтов будет 32 × 32. Однако общий объем памяти составляет более 253984 байта. На современном процессоре это означает 32 или 33 остановки кеша . Напротив, если бы изображение было 128 × 8192, диапазон памяти был бы только 4000 байтов, что означает не более двух остановок кэша.

Поскольку современные процессоры очень быстрые, кэш-память стоит очень дорого и требует больших вычислений. Таким образом, использование изображения 128 × 8192 вместо изображения 8192 × 128 потенциально в 8 раз быстрее, по крайней мере в теории. На практике это будет зависеть от того, как будет реализован блитинг: возможно, что базовый механизм сам разбивает изображения на фрагменты, чтобы уменьшить проблему.

Это нелегко объяснить правильно, и я не ожидал, что укажу много. Я надеюсь, что это имеет смысл!


4
«Обратите также внимание на то, что из-за эффективности доступа к памяти вы никогда не должны делать свои спрайт-листы слишком широкими. Перекрытие фрагментов изображения 128 × 8192 всегда будет быстрее, чем блики изображения 8192 × 128». - любопытство, не могли бы вы уточнить, пожалуйста? :)
— Гримшоу

@DevilWithin: я пытался объяснить проблему; дайте мне знать, если я достаточно ясно
— Сам Хочевар

Эффективность кеша впечатляет. Есть ли у вас какие-либо цифры на разницу, что это делает в отношении частоты кадров?
— Грегори Эйвери-Вейр

Является ли это проблемой, похоже на конкретную реализацию, но если API, такой как OpenGL, действует на текстуры таким образом, важно принять это во внимание, спасибо :)
— Grimshaw

2
@DevilWithin: то, что я написал, действительно только для CPU - GPU, будучи массивно параллельным, имеет очень разные настройки кэша и будет хранить текстуры, используя собственный внутренний формат, оптимизированный для произвольного доступа. По этой причине в OpenGL рекомендуются квадратные текстуры со степенью двух, и я бы следовал этому правилу и для наборов плиток.
— Сам Хочевар

5

Одна огромная таблица спрайтов (вероятно) даст вам лучшую производительность, просто потому, что одной из главных причин отставания является обратная передача от запроса браузера к серверу и браузеру. 10000 HTTP-вызовов займет намного больше времени, чем 1 HTTP-вызов, который возвращает файл, который на 10000 больше.

Могут быть и другие вещи, которые вы можете использовать для уменьшения задержки, в зависимости от структуры игры и HTML, который вы создаете.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.