Dans un navigateur, est-il préférable d’utiliser une grande feuille de calcul ou plusieurs (10000) PNG différents?

33

Je crée un jeu dans jQuery, où j'utilise environ 10000 tuiles 32x32. Jusqu'à présent, je les utilisais tous séparément (pas de feuille de sprite). Une carte moyenne utilise environ 2 000 tuiles (fichiers PNG parfois réutilisés, mais tous les div séparés) et les performances vont de stable (Chrome) à un peu lent (Firefox). Chacune de ces divs est positionnée de manière absolue en utilisant CSS. Ils n'ont pas besoin d'être mis à jour à chaque tick, juste au chargement d'une nouvelle carte.

Serait-il préférable, pour les performances, d’utiliser les méthodes spritesheet pour les div en utilisant le positionnement en arrière-plan CSS, comme le fait gameQuery?

Merci d'avance!

Entaille
la source
3
Où diable avez-vous besoin de 10 000 tuiles pour la carte? Je vous suggère de ne pas télécharger / dessiner toute la carte côté utilisateur. Montrer seulement une partie, qui est visible. Lorsque l'utilisateur se déplace, charge la section suivante. La façon dont chaque graphique 3D fonctionne.
Deele
Une carte moyenne utilise 2000 tuiles différentes, ou seulement 2000 tuiles au total? Quelle est la taille des cartes que vous créez?
Nick Larsen
Avez-vous envisagé d'utiliser une ou plusieurs images plus grandes comme arrière-plan et d'effectuer une détection de collision polygonale pour les limites?
SAHornickel

Réponses:

50

Ma suggestion

Trop de petits fichiers PNG ajouteront beaucoup de charge réseau (en raison de la taille des requêtes HTTP, mais aussi de l'en-tête PNG et, ce qui est probablement encore plus important, de l'impossibilité de compresser efficacement). D'autre part, un très grand fichier PNG présente les inconvénients qu'il faut du temps pour le charger et qu'il doit rester en permanence en mémoire (40 mégaoctets pour 10 000 tuiles) dans une partie continue de la mémoire.

Je recommande le moyen terme: plusieurs PNG de taille raisonnable, par exemple 1024 dalles de format 32 × 32 . Peut-être regroupés par thème (par exemple, un PNG avec des tuiles de forêt, un avec des tuiles de montagne, un autre avec des tuiles de ville - je ne connais pas le thème de votre jeu, mais vous en avez l'idée).

Note sur l'efficacité du cache

En raison de l’efficacité de l’accès à la mémoire, vous ne devriez jamais trop élargir vos feuilles d’image. La fusion de carreaux à partir d'une image 128 × 8192 sera toujours plus rapide que celle obtenue à partir d'une image 8192 × 128.

Imaginez que vous souhaitiez supprimer la première tuile d’une image 8192 × 128. Par souci de simplicité, supposons qu'un pixel soit un octet. Les deux premières lignes de pixels sont disposées de cette façon (les cellules contiennent leur numéro d’octet en mémoire):

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

Ainsi, afin de supprimer la première ligne du premier titre, le moteur de navigation récupérera des octets 0dans31 . Pour effacer la deuxième ligne , il va récupérer les octets 8192à8223 , et ainsi de suite jusqu'à la ligne où 32e octets 253952à253983 sont récupérés.

Le nombre total d'octets traités sera de 32 × 32. Cependant, la plage de mémoire totale est supérieure à 253984 octets. Sur un processeur moderne, cela signifie 32 ou 33 stalles de cache . En revanche, si l’image était au format 128 × 8192, la plage de mémoire ne serait que de 4000 octets, ce qui signifie pas plus de deux stalles de cache.

Les processeurs actuels étant très rapides, les stalles de cache coûtent très cher et bloquent les calculs. Donc, utiliser une image 128 × 8192 au lieu d'une image 8192 × 128 est potentiellement 8 fois plus rapide, du moins en théorie. En pratique, cela dépendra de la manière dont le fondu est mis en oeuvre: il est possible que le moteur sous-jacent divise lui-même les images en mosaïques pour réduire le problème.

Ce n'est pas facile à expliquer correctement et je ne m'attendais pas à beaucoup élaborer. J'espère que ça a du sens!

sam hocevar
la source
4
"Notez également qu'en raison de l'efficacité de l'accès mémoire, vous ne devriez jamais élargir trop votre feuille de sprite. Bliter les tuiles à partir d'une image 128 × 8192 sera toujours plus rapide que celui à partir d'une image 8192 × 128." - Bonne curiosité, voudriez-vous élaborer s'il vous plaît? :)
Grimshaw
@DevilWithin: J'ai essayé d'expliquer le problème. laissez-moi savoir si je suis assez clair!
Sam Hocevar
L'efficacité de la cache est fascinante. Avez-vous des chiffres sur la différence en ce qui concerne le framerate?
Gregory Avery-Weir
Que ce soit un problème, cela ressemble à une implémentation spécifique, mais si une API comme OpenGL agit sur les textures de cette façon, il est important de prendre cela en considération, merci :)
Grimshaw
2
@DevilWithin: ce que j'ai écrit n'est valable que pour un CPU - un GPU, massivement parallèle, possède des paramètres de cache très différents et stockera les textures dans son propre format interne, optimisé pour un accès aléatoire. C'est la raison pour laquelle les textures carrées à la puissance de deux sont recommandées dans OpenGL, et je suivrais également cette règle pour les jeux de carreaux.
Sam Hocevar
5

Une feuille de calcul extrêmement volumineuse vous offrira (probablement) de meilleures performances, tout simplement parce que l’une des principales causes de décalage est le va-et-vient entre requêtes de navigateur, serveur à navigateur. 10 000 appels HTTP prendront beaucoup plus longtemps qu'un appel HTTP renvoyant un fichier 10 000 plus volumineux.

Il est possible que vous puissiez utiliser d'autres options pour réduire le délai, en fonction de la structure du jeu et du code HTML créé.

thédien
la source