Perché i modelli 3D sono così pesanti?
Il tuo modello si sta ingrassando di nascosto
Hai esportato un file GLB, 10MB, sembra a posto. Lo apri sul telefono: schermata bianca, scatti, o addirittura un crash.
Sul computer nessun problema, sul telefono esplode. Non è colpa del codice. È una proprietà poco intuitiva dei modelli 3D: su disco e in memoria video, le dimensioni sono completamente diverse.
Un'immagine JPG su disco può essere solo 200KB. Ma la GPU non capisce il JPG; capisce solo i pixel grezzi. Quindi, prima di essere caricata in memoria video, l'immagine viene completamente decompressa. Una texture 2048x2048 consuma circa 22MB di memoria video una volta decompressa. Se usi 6 texture (albedo, normal, roughness, metallic, AO, emissive), un solo materiale costa 132MB.
Un telefono potrebbe avere in totale solo 2-4GB di memoria video, e le texture di un solo modello ne consumano il 3-6%. E se nella scena ci sono 10 modelli?
Apriamolo: dove vanno i byte
Un tipico modello GLB è composto da tre parti principali: dati dei vertici, texture, e metadati più animazioni.
Prendi un modello PBR reale:
| Componente | Cosa è | Quota tipica | Note |
|---|---|---|---|
| Texture | albedo, normal, roughness, metallic, AO, ecc. | 70-85% | Quasi sempre il grosso |
| Dati dei vertici | position, normal, UV, tangent, color | 10-20% | Dipende dalla complessità |
| Dati di animazione | scheletri, skinning, keyframe | 0-15% | Solo se animato |
| Altro | definizioni materiali, struttura scena, camere | < 2% | Trascurabile |
Le texture occupano circa l'80%. Spesso pensi che siano i vertici a dover essere ottimizzati, ma ciò che occupa davvero spazio sono le texture.
"Piccolo su disco" non significa "piccolo in memoria video"
Questo è forse il punto più importante per capire le prestazioni 3D.
PNG e JPG sono progettati per il trasferimento di rete——piccoli su disco, veloci da scaricare. Ma la GPU non può usarli direttamente; devono essere prima completamente decompressi in pixel grezzi. La formula:
VRAM = larghezza * altezza * 4 byte (RGBA) * 1.333 (con mipmap)
Una texture RGBA 4096x4096:
| Metrica | Valore |
|---|---|
| Dimensione file PNG | ~8MB |
| Dimensione file JPG | ~1.5MB |
| Uso VRAM (con mipmap) | ~87MB |
Un JPG da 1.5MB diventa 87MB in memoria video.
Cosa sono le mipmap? La GPU genera una serie di versioni progressivamente più piccole di una texture, dalla dimensione originale fino a 1x1 pixel, ogni livello la metà del precedente. Questo rende gli oggetti lontani più veloci e nitidi da renderizzare, ma costa circa il 33% di memoria video in più. Quasi ogni applicazione 3D usa le mipmap, quindi questo overhead è praticamente standard.
Quindi PNG e JPG sono come le sacche sottovuoto——compresse e piccole per il viaggio, ma devi espanderle completamente a destinazione. Il download è più veloce, ma il risparmio di memoria video è zero.
Cosa succede quando la memoria video finisce
Non avrai un bel dialogo "memoria insufficiente". La realtà è peggiore:
- Mobile: schermata bianca, o il sistema operativo chiude direttamente la scheda
- Visori VR: frame drop. Nella VR un frame perso non è "un po' di lag"——provoca nausea
- Desktop: sfarfallio delle texture, degrado, rendering più lento
Su Reddit, uno sviluppatore ha costruito una galleria WebXR e ha stipulato 60 immagini stereoscopiche su un Quest. All'inizio funzionava, poi è diventato sempre più instabile fino al crash. Ha passato giorni a debuggare il codice prima di rendersi conto che non aveva mai pensato seriamente alla VRAM——stava solo continuando a infilare JPG nella GPU.
Due vie per la compressione
La compressione dei modelli 3D si divide in due direzioni:
Compressione dei vertici——memorizza i dati geometrici (coordinate dei vertici, normali, UV) in modo più compatto. Ad esempio, scambiando float a 32 bit con interi a 16 bit (questo si chiama quantizzazione). Soluzioni rappresentative: Draco, MeshOpt, KHR_mesh_quantization.
Compressione delle texture——mantiene le texture compresse anche dentro la memoria video. La GPU decodifica i singoli pixel al volo durante il campionamento, quasi senza costo prestazionale. Soluzione rappresentativa: KTX2 + Basis Universal.
| Compressione vertici | Compressione texture | |
|---|---|---|
| Cosa riduce | Dati geometrici | Texture |
| Effetto tipico | 50-90% più piccolo | 50-70% più piccolo su disco, 75% di VRAM in meno |
| Con perdita? | Sì, perdita di precisione | Sì, perdita di qualità |
| Ideale per | Modelli densi di vertici | Quasi ogni modello PBR |
| Vedi | Parte 2 | Parti 3 e 4 |
Un malinteso comune: comprimere i vertici con Draco e dire "fatto". Ma le texture sono l'80% delle dimensioni del modello——dimezza i vertici e il tutto potrebbe ridursi solo del 10%. Devi lavorare su entrambi i fronti.
Nessun metodo vince ovunque
Questa è la tesi centrale dell'intera serie:
Piattaforme, dispositivi e casi d'uso diversi richiedono strategie di compressione diverse.
| Scenario | Collo di bottiglia principale | Focus |
|---|---|---|
| Showcase web desktop | Velocità di download | Dimensione file |
| Browser mobile | Memoria video | Compressione texture |
| Visore VR | Memoria video + frame rate | Compressione texture + semplificazione vertici |
| WeChat Mini Program | Dimensione pacchetto + compatibilità | Opzioni leggere (MeshOpt) |
| Scene grandi | Memoria video + draw call | Compressione completa + LOD |
Ogni prossimo articolo non dirà solo "usa X e hai finito". Spiegherà: dove X brilla, quando si ritorce contro, e quando dovresti invece usare Y.
Prossimi passi
Questo articolo ha inquadrato il problema. Il prossimo si fa pratico——incontro con i tre strumenti della compressione dei vertici: quantizzazione, MeshOpt e Draco.