En un navegador, ¿es mejor usar una gran hoja de sprites o muchos (10000) PNG diferentes?

33

Estoy creando un juego en jQuery, donde uso alrededor de 10000 fichas de 32x32. Hasta ahora, los he estado usando todos por separado (sin hoja de sprites). Un mapa promedio usa alrededor de 2000 mosaicos (a veces reutilizados PNG pero todos los divs separados) y el rendimiento varía de estable (Chrome) a un poco lento (Firefox). Cada uno de estos divs se posicionan absolutamente usando CSS. No es necesario que se actualicen cada tic, solo cuando se carga un nuevo mapa.

¿Sería mejor para el rendimiento usar métodos de hoja de sprites para los divs que usan posicionamiento de fondo CSS, como hace gameQuery?

¡Gracias de antemano!

Mella
fuente
3
¿Dónde diablos necesitas 10 000 fichas para el mapa? Le sugiero que no cargue / dibuje todo el mapa en el lado del usuario. Muestra solo una parte, que es visible. Cuando el usuario se mueve, cargue la siguiente sección. La forma en que funcionan todos los gráficos 3D.
Deele
¿Un mapa promedio usa 2000 fichas diferentes, o solo 2000 fichas totales? ¿Qué tan grandes son los mapas que estás creando?
Nick Larsen
¿Ha considerado usar una o algunas imágenes más grandes como fondo y realizar una detección de colisión poligonal para los límites?
SAHornickel

Respuestas:

50

Mi sugerencia

Demasiados PNG pequeños agregarán una gran sobrecarga de red (debido al tamaño de las solicitudes HTTP, pero también al encabezado PNG y, lo que es más importante, la incapacidad de comprimir de manera eficiente). Por otro lado, un PNG muy grande tiene los inconvenientes que lleva un tiempo cargar, y necesita permanecer permanentemente en la memoria (40 megabytes por 10,000 mosaicos) en una porción continua de memoria.

Recomiendo el término medio: varios PNG de tamaño razonable, por ejemplo 1024 mosaicos de tamaño 32 × 32 . Tal vez agrupados por tema (por ejemplo, un PNG con fichas de bosque, uno con fichas de montaña, otro con fichas de ciudad; no sé el tema de tu juego, pero entiendes la idea).

Nota sobre la eficiencia del caché

Debido a la eficiencia del acceso a la memoria, nunca debe hacer que sus hojas de sprites sean demasiado anchas. Los mosaicos brillantes de una imagen de 128 × 8192 siempre serán más rápidos que el borrado de una imagen de 8192 × 128.

Imagine que quiere borrar el primer mosaico en una imagen de 8192 × 128. En aras de la simplicidad, suponga que 1 píxel es 1 byte. Las primeras dos líneas de píxeles se presentan de esta manera (las celdas contienen su número de bytes en la memoria):

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

Así que con el fin de blit la primera línea del primer título, el motor del navegador recuperará bytes 0a31 . Para blit la segunda línea , se recuperará bytes 8192a8223 , y así sucesivamente hasta la línea de 32 bytes, donde 253952a253983 se recuperan.

El número total de bytes procesados ​​será 32 × 32. Sin embargo, el rango de memoria total es más de 253984 bytes. En una CPU moderna, esto significa 32 o 33 puestos de caché . Por el contrario, si la imagen fuera 128 × 8192, el rango de memoria sería de solo 4000 bytes, lo que significa que no más de dos puestos de caché.

Debido a que las CPU actuales son muy rápidas, las paradas de caché son muy caras y bloquean los cálculos. Por lo tanto, usar una imagen de 128 × 8192 en lugar de una imagen de 8192 × 128 es potencialmente 8 veces más rápido, al menos en teoría. En la práctica, esto dependerá de cómo se implemente el bliting: es posible que el motor subyacente mismo divida las imágenes en mosaicos para reducir el problema.

Esto no es fácil de explicar correctamente y no esperaba elaborar mucho. ¡Espero que tenga sentido!

sam hocevar
fuente
44
"Tenga en cuenta también que, debido a la eficacia del acceso a la memoria, nunca debe hacer que sus hojas de sprites sean demasiado anchas. Las baldosas brillantes de una imagen de 128 × 8192 siempre serán más rápidas que el borrado de una imagen de 8192 × 128". - Bonita curiosidad, ¿podrías elaborar por favor? :)
Grimshaw
@DevilWithin: he tratado de explicar el problema; ¡avíseme si estoy siendo lo suficientemente claro!
Sam Hocevar
La eficiencia de la caché es fascinante. ¿Tiene algún número sobre la diferencia que esto hace con respecto a la velocidad de fotogramas?
Gregory Avery-Weir
Si se trata de un problema, parece una implementación específica, pero si API como OpenGL actúa sobre las texturas de esa manera, es importante tenerlo en cuenta, gracias :)
Grimshaw
2
@DevilWithin: lo que escribí solo es válido para una CPU: una GPU, que es masivamente paralela, tiene configuraciones de caché muy diferentes y almacenará texturas usando su propio formato interno, optimizado para acceso aleatorio. Esta es la razón por la cual las texturas cuadradas de potencia de dos se recomiendan en OpenGL, y también seguiría esa regla para los conjuntos de mosaicos.
sam hocevar
5

Es probable que una gran hoja de sprites le brinde un mejor rendimiento, simplemente porque una de las principales causas del retraso es el viaje de ida y vuelta desde la solicitud del navegador al servidor al navegador. 10,000 llamadas HTTP tomarán mucho, mucho más tiempo que 1 llamada HTTP que devuelve un archivo que es 10,000 más grande.

Puede haber otras cosas que puede usar para disminuir el retraso, según la estructura del juego y el HTML que está creando.

thedaian
fuente