# Come liberare le risorse ([name])

Un aspetto importante per migliorare le prestazioni ed evitare perdite di memoria nella tua applicazione è l'eliminazione delle entità della libreria non utilizzate. Ogni volta che viene creata un'istanza di un tipo *three.js*, viene allocata una certa quantità di memoria. Tuttavia, *three.js* crea per oggetti specifici come le geometrie o i materiali, entità correlate WebGL, come buffer o programmi shader, necessari per il rendering. È importante sottolineare che questi oggetti non vengono rilasciati automaticamente. Invece, l'applicazione utilizza una speciale API per liberare tali risorse. Questa guida fornisce una breve panoramica su come l'API viene utilizzata e quali oggetti sono rilevanti in questo contesto.

## Geometrie

Una geometria solitamente rappresenta le informazioni sui vertici come una collezione di attributi. *three.js* internamente crea un oggetto di tipo [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer] per ogni attributo. Queste entità vengono cancellate solo se viene chiamato il metodo [page:BufferGeometry.dispose](). Se una geometria, nella tua applicazione, diventa obsoleta, esegui questo metodo per liberare tutte le risorse correlate.

## Materiali

Un materiale definisce come sono visualizzati gli oggetti. *three.js* utilizza le informazioni di una definizione di materiale per costruire un programma shader per il rendering. I programmi shader possono essere cancellati solo se il respettivo materiale è eliminato. Per ragioni di prestazioni, *three.js* prova, se possibile, a riutilizzare il programma shader già esiste. Quindi un progamma di shader può essere cancellato solo se tutti i relativi materiali sono eliminati. Puoi eseguire l'eliminazione di un materiale eseguendo il metodo [page:Material.dispose]().

## Texture

L'eliminazione di un materiale non ha effetti sulle texture. Queste vengono gestite separatamente, poiché una singola texture può essere usata da più materiali contemporaneamente. Ogni volta che crei un'istanza di [page:Texture], three.js internamente crea un'istanza di [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture WebGLTexture]. Come per i buffer, questo oggetto può essere eliminato solo chiamando il metodo[page:Texture.dispose]().

Se stai usando `ImageBitmap` come origine dati della texture, devi chiamare il metodo [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap/close ImageBitmap.close]() a livello applicativo per liberare le risorse lato CPU. Una chiamata automatica di `ImageBitmap.close()`in [page:Texture.dispose]() non è possibile, poiché il bitmap dell'immagine diventa inutilizzabile, e l'engine non ha modo di sapere se il bitmap dell'immagine è utilizzata da altre parti.

## Render Target

Oggetti di tipo [page:WebGLRenderTarget] non allocano solo un'istanza di [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture WebGLTexture] ma anche di [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLFramebuffer WebGLFramebuffer] e di [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderbuffer WebGLRenderbuffer] per realizzare destinazioni di rendering personalizzate. Questi oggetti vengono solo deallocati eseguendo il metodo [page:WebGLRenderTarget.dispose]().

## Varie

Ci sono altre classi nella cartella degli esempi come i control o passaggi di post-processing che forniscono metodi `dispose()` per rimuovere i listener di eventi interni o renderizzare i target. In generale, viene raccomandato di controllare le API o la documentazione della classe e controllare il metodo `dispose()`. Se presente dovresti utilizzarlo per liberare le risorse.

## FAQ

### Perché *three.js* non può eliminare gli oggetti automaticamente?

Questa domanda è stata fatta spesso dalla community, quindi è importante chiarire la questione. Il fatto è che *three.js* non conosce il ciclo di vita o lo scopo delle entità create dall'utente come le geometrie o i materiali, questa è una responsabilità dell'applicazione. Per esempio, anche se un materiale non è momentamenente utilizzato per il rendering, potrebbe essere necessario per il prossimo frame. Quindi se l'applicazione decide che un determianto oggetto può essere cancellato lo notifica all'engine tramite la chiamata al rispettivo metodo `dispose()`.

### La rimozione di una mesh dalla scena elimina anche la sua geometria e il suo materiale?

No, devi eliminare esplicitamente la geometria e il materiale chiamando il metodo *dispose()*. Tieni a mente che le geometrie e i materiali possono essere condivisi tra oggetti 3D come le mesh.

### *three.js* fornisce informazioni sulla quantità di oggetti memorizzati nella cache?

Si, è possibile consultare [page:WebGLRenderer.info]. Una proprietà speciale del renderer con una serie di informazioni statistiche sulla memoria della scheda grafica e il processo di rendering. Tra le altre cose, riporta anche quante texture, geometrie e programmi shader sono internamente memorizzati. Se noti che ci sono problemi di performance nell'applicazione, è una buona idea debuggare questa proprietà per identificare facilmente se c'è una perdita di memoria.

### Che cosa succede quando il metodo `dispose()` viene chiamato su una texture ma l'immagine non è ancora stata caricata?

Le risorse interne di una texture vengono allocate solo se l'immagine è caricata con successo. Se elimini una texture prima che l'immagine venga caricata non succede niente. Nessuna risorsa è stata allocata, quindi niente deve essere pulito.

### Cosa succede quando chiamo `dispose()` e poi utilizzo il rispettivo oggetto in un secondo momento?

Le risorse interne che sono state cancellate saranno ricreate dall'engine, in questo modo non ci saranno errori a runtime. Probabilmente, però, noterai un impatto negativo sulle performance nel frame corrente quando il programma shader sarà compilato.

### Come devo gestire gli oggetti *three.js* nella mia app? Quando so che devo eliminare le risorse?

In generale non c'è una raccomandazione definitiva per questo. Dipende molto dal caso d'uso specifico. È importante sottolineare che non è sempre necessario eliminare oggetti tutto il tempo. Un buon esempio esemplificativo è un gioco a più livelli. Un buon momento per eliminare gli oggetti è quando viene cambiato il livello. L'applicazione può attraversare tutta la vecchia scena (livello) ed eliminare tutti i vecchi materiali, geometrie e texture. Come accennato nella sezione precedente, se viene cancellato un oggetto che è attualmente in uso non produce un errore a runtime. La cosa peggiore che può accadere è un calo delle prestazioni in un singolo frame.

## Esempi che mostarno l'uso del metodo dispose()

[example:webgl_test_memory WebGL / test / memory]
[example:webgl_test_memory2 WebGL / test / memory2]