Come risolviamo i grandi requisiti di memoria video in un gioco 2D?
Stiamo sviluppando un gioco 2D (Factorio) in allegro C / C ++ e stiamo affrontando un problema con l'aumento dei requisiti di memoria video all'aumentare del contenuto del gioco.
Attualmente raccogliamo tutte le informazioni sulle immagini che verranno utilizzate per prime, ritagliamo tutte queste immagini il più possibile e le organizziamo in grandi atlanti il più strettamente possibile. Questi atlanti sono memorizzati nella memoria video, la cui dimensione dipende dalle limitazioni del sistema; attualmente sono normalmente 2 immagini fino a 8192x8192, quindi richiedono una memoria video da 256 Mb a 512 Mb.
Questo sistema funziona abbastanza bene per noi, poiché con alcune ottimizzazioni personalizzate e la suddivisione del thread di rendering e aggiornamento siamo in grado di disegnare decine di migliaia di immagini sullo schermo a 60 fps; abbiamo molti oggetti sullo schermo e consentire un grande ingrandimento è un requisito fondamentale. Come vorremmo aggiungere altro, ci saranno alcuni problemi con i requisiti di memoria video, quindi questo sistema non può contenere.
Una delle cose che volevamo provare è avere un atlante con le immagini più comuni e il secondo come cache. Le immagini sarebbero state spostate lì dalla memoria bitmap, su richiesta. Ci sono due problemi con questo approccio:
- Il disegno da bitmap di memoria a bitmap video è dolorosamente lento, in allegro.
- Non è possibile lavorare con bitmap video in altro che nel thread principale, in allegro, quindi è praticamente inutilizzabile.
Ecco alcuni requisiti aggiuntivi che abbiamo:
- Il gioco deve essere deterministico, quindi i problemi di prestazioni / i tempi di caricamento non possono mai modificare lo stato del gioco.
- Il gioco è in tempo reale e presto sarà anche multiplayer. Dobbiamo evitare anche la più piccola balbuzie a tutti i costi.
- Gran parte del gioco è un mondo aperto continuo.
Il test consisteva nel disegnare 10 000 sprite in un batch per dimensioni da 1x1 a 300x300, più volte per ogni configurazione. Ho fatto i test sulla Nvidia Geforce GTX 760.
- Dal bitmap video al disegno del bitmap video sono stati impiegati 0,1 us per sprite, quando la bitmap di origine non cambiava tra le singole bitmap (la variante dell'atlante); le dimensioni non contavano
- Da bitmap video a disegno di bitmap video, mentre la bitmap di origine è stata commutata tra disegni (variante non atlante), ha richiesto 0,56us per sprite; la dimensione non importava, neanche.
- La memoria da bitmap a disegno di bitmap video era davvero sospetta. Le dimensioni da 1x1 a 200x200 hanno richiesto 0,3us per bitmap, quindi non così orribilmente lente. Per taglie più grandi, il tempo ha iniziato a salire molto drammaticamente, a 9us per 201x201 a 3116us per 291x291.
L'uso dell'atlante aumenta le prestazioni di un fattore maggiore di 5. Se avessi 10 ms per il rendering, con un atlante sono limitato a 100.000 sprite per frame e senza di esso un limite di 20.000 sprite. Questo sarebbe problematico.
Stavo anche cercando di trovare un modo per testare la compressione bitmap e il formato bitmap 1bpp per le ombre, ma non sono riuscito a trovare un modo per farlo in allegro.