Hvor kommer alle bytes fra?

Fantastisk spørgsmål Dion! Jeg vil svare på det, og ikke kun fordi du er min nye chef, men fordi det er et godt spørgsmål. (men også fordi du er min nye chef.)

Jeg vil dog indstille noget klart her: vi sammenligner ikke rigtig æbler til æbler, så lad os først definere nogle teknologier.

Hvordan Mario fungerer

Så lad os tale om, hvordan det originale Super Mario-spil fungerede ud fra et aktivperspektiv.

Den originale NES-konsol var kun designet til at sende billeder, der var 256 brede og 240 høje; hvilket betyder, at det endelige billede, der skulle vises på skærmen, var 180 kb i størrelse.

Derudover havde NES kun 2 kb RAM. En patron i sig selv kunne indeholde 8k til 1mb af spildata. Så der var ingen måde at tilpasse hele spilets indhold til hovedhukommelsen. Dybest set skal et undersæt af 1 MB patrondata indlæses i 2 kb RAM og bruges til at gengive 180 kb-skærmen. Hvordan opnår man det?

SpriteSheets.

Sprite-ark indeholder små fliser med grafik, der genbruges igen og igen. For eksempel er nedenfor en genindspilning af det originale super mario sprite ark:

Hver lille firkant på 16x16 pixel repræsenterer en "flise", og kunstnerne strenger disse sammen for at skabe de faktiske niveauer. Selve niveauerne blev netop en kæmpe 2D-række indekser i sprite-arket. (Jeg taler meget mere om dette i lektion 3 i mit HTML5-spiludviklingskursus @ Udacity eller i min bog HTML5-spiludviklingsindsigt.) Tack på nogle kørelængdekodning eller nogle grundlæggende LZ77, og du får en ret kompakt format til niveauer.

Så med begreber som fliseark og sprite-ark kan vi bruge et lille sæt billeder til at skabe store scener og verdener. Dette er generelt, hvordan de fleste spil fungerer. Selv 3D-spil vil have et sæt almindelige strukturer, der anvendes flere gange og steder i selve spillet.

Lad os nu tale om generisk billedkomprimering.

Hvordan billeder komprimeres

Her er den " ikke retfærdige " del af denne sammenligning. Generiske billedkomprimeringsalgoritmer har ingen domæne viden om pixels inde i dem. JPG, PNG, WebP har alle blevet designet til fotos og ikke så meget spil skærme . Resultatet er, at for en given blok på 16x16 pixel antager disse algoritmer, at den er unik blandt billedet; Udover en vis farvekvantisering er der ikke tilføjet nogen reel logik for at afgøre, om en anden 16x16-blok kunne være et nøjagtigt duplikat af den aktuelle. Dette betyder generelt, at der er en lavere grænse for, hvordan en given datablok komprimeres.

For eksempel bryder JPG et givet billede i 8x8 pixelblokke, konverterer RGB-farveområdet til YCbCr-versionen og anvender derefter Diskret cosinustransformation på dem. Det er først efter dette trin, kommer en tabsfri koder sammen og ser, om den kan matche almindelige duplikatgrupper ved hjælp af DPCM eller RLE.

Så det eneste sted, hvor to blokke måske komprimeres til 1 blok, er, hvis deres post-DCTd-version er identisk, og RLE kan komme med skridtanbefalinger. Dette sker ikke så ofte.

På trods af sine andre mangler er PNG meget bedre i denne henseende. PNG-komprimering er helt tabsfri (så din billedkvalitet er høj, men din komprimeringsbesparelse er lav) og baseret på DEFLATE-codec, som parrer LZSS sammen med aritmetisk kompression. Resultatet er, at lange kørsler med lignende pixels kan ende med at blive skåret ned til en meget mindre størrelse. Dette er grunden til, at et billede med en meget ensartet baggrund altid vil være mindre som en PNG i stedet for en JPG.

Nedenstående billede er en 5,9 kb PNG-fil, mens JPG-billedet er 106 kb

Æbler vs Dragonfruit

Mit punkt her er, at det er lidt uretfærdigt at sammenligne spilindhold med et enkelt billede på internettet.

Fra spilsiden starter du med et lille sæt genanvendelige fliser og indekserer dem for at opbygge dit større billede, vi kan gøre dette, fordi vi ved, hvordan spillet skal laves. På den anden side forsøger JPG / PNG / WebP bare at komprimere de data, de kan finde i lokale blokke, uden noget reelt ønske om at matche gentaget indhold. Billedkomprimering er tydeligvis en ulempe her, da de ikke har forudgående kendskab til deres datarum, kan de ikke rigtig stille nogen forventninger til det.

Jeg mener, overveje The Demo Scene, som er super stor på denne slags ting. De kan klemme 30 minutter af en hel 3d-skydespil ind i 64 kb, fordi de forstår og ved så meget mere om deres data.

Det viser bare, med den rigtige mængde forudviden om dine data, kan du gøre gode ting med komprimering.

Ser frem til.

Vi er åbenbart vokset op siden NES-dages 256x240-skærme. Telefonen i lommen har 1.920 x 1.080 skærmpixels @ den er 5,2 ”-størrelse, hvilket giver den ~ 423 pixels pr. Tomme tæthed. For at sammenligne det i det samme antal pixels, der er ~ 33 super-mario-skærme, eller rettere, 8 MB pixeldata. Jeg tror ikke nogen er overrasket over, at skærmopløsningerne stiger, men det kommer også med behovet for flere data .

Dette er noget, jeg har harpet på i et stykke tid nu. Mens vi får større skærme, skal indholdskanalerne øge deres opløsningsoutput for stadig at se godt ud i vores opsætninger med højere tæthed (ellers får vi skalering af slørhed ..). Dette får naturligvis vores videospilpakker til at vokse i størrelse, vores websider vokser i størrelse, og endda vores youtube-streamingvideoer vokser i størrelse. Dybest set sender vi flere data til mindre enheder simpelthen på grund af skærmopløsning. Hvilket for de næste 2 milliarder mennesker på nye markeder på 2G-forbindelser er som den værste idé nogensinde.

Men jeg afviger. Det er et andet indlæg.