Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Occlusion culling

In un motore di rendering 3D, l'occlusion culling è il processo di rimozione della geometria nascosta.

In questa pagina imparerai:

  • Quali sono i vantaggi e le insidie dell'occlusion culling.

  • Come configurare l'occlusion culling in Godot.

  • Risolvere problemi comuni con l'occlusion culling.

Vedi anche

È possibile osservare il funzionamento dell'occlusion culling in azione attraverso il progetto demo Occlusion Culling and Mesh LOD.

Perché utilizzare l'occlusion culling

In questa scena di esempio con centinaia di stanze una accanto all'altra, un oggetto dinamico (sfera rossa) è nascosto dietro il muro nella stanza illuminata (a sinistra della porta):

Scena di esempio con un layout adatto all'occlusion culling

Scena di esempio con un layout adatto all'occlusion culling

Con l'occlusion culling disabilitato, tutte le stanze dietro la stanza illuminata devono essere renderizzate. Anche l'oggetto dinamico deve essere renderizzato:

Scena di esempio con occlusion culling disabilitato (fildiferro)

Scena di esempio con occlusion culling disabilitato (fildiferro)

Con l'occlusion culling abilitato, solo le stanze effettivamente visibili devono essere renderizzate. Anche l'oggetto dinamico viene occluso dal muro e quindi non deve più essere renderizzato:

Scena di esempio con occlusion culling abilitato (fildiferro)

Scena di esempio con occlusion culling abilitato (fildiferro)

Poiché il motore ha meno lavoro da fare (meno vertici da renderizzare e meno chiamate di disegno), le prestazioni aumenteranno, purché nella scena siano presenti sufficienti opportunità per l'occlusion culling. Significa che l'occlusion culling è più efficace nelle scene interne, preferibilmente con molte stanze piccole anziché poche stanze più grandi. Combinando questo con Mesh level of detail (LOD) e Campi di visibilità (HLOD) si possono migliorare ulteriormente le prestazioni.

Nota

Quando si utilizza il renderer Forward+, il motore esegue già un pre-passaggio di profondità. Consiste nel renderizzare una versione della scena che mostra solo la profondità prima di renderizzare i materiali effettivi della scena. Ciò serve a garantire che ogni pixel opaco venga ombreggiato una sola volta, riducendo significativamente l'impatto dell'overdraw.

Le prestazioni possono migliorare specialmente per il renderer Mobile, poiché non include un pre-passaggio di profondità per ragioni di prestazioni. Pertanto, l'occlusion culling ridurrà attivamente l'overdraw di ombreggiatura con tale renderer.

Tuttavia, anche utilizzando un pre-passaggio di profondità, l'occlusion culling è comunque molto vantaggioso nelle scene 3D complesse. Nelle scene con poche opportunità di occlusion culling, però, la configurazione in più e l'utilizzo della CPU potrebbero non valerne la pena.

Come l'occlusion culling funziona in Godot

Nota

"occlusore" si riferisce alla forma che blocca la vista, mentre "occluso" si riferisce all'oggetto che viene nascosto.

In Godot, l'occlusion culling funziona rasterizzando la geometria dell'occlusore della scena in un buffer a bassa risoluzione sulla CPU. Lo si fa attraverso la libreria di raytracing in software Embree.

Il motore utilizza quindi questo buffer a bassa risoluzione per confrontare l'AABB dell'oggetto occluso con le forme dell'occlusore. l'AABB dell'oggetto occluso deve essere completamente occluso dalla forma dell'occlusore per essere scartato.

Di conseguenza, è più probabile che siano scartati effettivamente gli oggetti più piccoli rispetto agli oggetti più grandi. Anche gli occlusori più grandi (come i muri) tendono ad essere molto più efficaci di quelli più piccoli (come gli oggetti decorativi).

Configurazione dell'occlusion culling

Il primo passo per utilizzare l'occlusion culling è abilitare l'impostazione del progetto Rendering > **Occlusion Culling > Usa Occlusion Culling. (Assicurati che l'opzione Avanzate sia abilitata nella finestra Impostazioni del progetto per poterla vedere.)

Questa impostazione del progetto viene applicata immediatamente, quindi non è necessario riavviare l'editor.

Dopo aver abilitato l'impostazione del progetto, bisogna comunque creare qualche occlusore. Per motivi di prestazioni, il motore non utilizza automaticamente tutta la geometria visibile come base per l'occlusion culling. Richiede invece una rappresentazione semplificata della scena con solo oggetti statici da preparare.

Ci sono due modi per configurare gli occlusori in una scena:

Posizionare manualmente gli occlusori

Questo approccio è più adatto a casi d'uso specifici, come la creazione di occlusioni per configurazioni MultiMeshInstance3D o nodi CSG (a causa della limitazione menzionata prima).

Dopo aver abilitato l'impostazione dell'occlusion culling menzionata prima, aggiungi un nodo OccluderInstance3D alla scena contenente il tuo livello 3D. Seleziona il nodo OccluderInstance3D, poi scegli un tipo di occlusore da aggiungere nella proprietà Occluder:

  • QuadOccluder3D (un singolo piano)

  • BoxOccluder3D (un cuboide)

  • SphereOccluder3D (un occlusore a forma di sfera)

  • PolygonOccluder3D (un poligono 2D con tutti i punti che si desiderano)

Esiste anche ArrayOccluder3D, i cui punti non si possono modificare nell'editor, ma può essere utile per la generazione procedurale da uno script.

Vedere in anteprima l'occlusion culling

È possibile abilitare una modalità di disegno di debug per vedere in anteprima ciò che l'occlusion culling sta effettivamente "vedendo". Nell'angolo superiore sinistro della viewport dell'editor 3D, clicca sul pulsante Prospettiva (o Ortogonale a seconda della modalità attuale della telecamera), poi scegliere Visualizza avanzati... > Buffer d'occlusion culling. Sarà visualizzato il buffer a bassa risoluzione utilizzato dal motore per l'occlusion culling.

Nello stesso menu, è anche possibile abilitare Vedi informazioni e Vedi tempo di frame per visualizzare il numero di chiamate di disegno e primitive renderizzate (vertici + indici) nell'angolo inferiore destro, insieme al numero di frame al secondo renderizzati nell'angolo superiore destro.

Se si cambia l'occlusion culling nelle impostazioni del progetto mentre queste informazioni sono visualizzate, puoi vedere quanto l'occlusion culling migliora le prestazioni nella tua scena. Tieni presente che il vantaggio sulle prestazioni dipende molto dall'angolazione della telecamera nell'editor 3D, poiché l'occlusion culling è efficace solo se ci sono occlusori davanti alla telecamera.

Per cambiare l'occlusion culling in fase di esecuzione, imposta use_occlusion_culling sulla viewport radice come segue:

get_tree().root.use_occlusion_culling = true

Cambiare l'occlusion culling in fase di esecuzione è utile per confrontare le prestazioni su un progetto in esecuzione.

Considerazioni sulle prestazioni

Progetta i tuoi livelli in modo da sfruttare l'occlusion culling

Questa è la linea guida più importante. Un buona progettazione non riguarda solo ciò che il gioco richiede; si dovrebbe anche costruire tenendo l'occlusione in mente.

Per gli ambienti interni, aggiungi pareti opache a intervalli regolari per "interrompere" la linea visiva e assicurarti che non si veda troppo nella scena alla volta.

Per le scene ampie e aperte, quando possibile, utilizza una struttura piramidale per l'elevazione del terreno. Questa offre le maggiori opportunità di culling rispetto a qualsiasi altra forma di terreno.

Evita di spostare i nodi OccluderInstance3D durante il gioco

Ciò include lo spostamento dei nodi genitori di OccluderInstance3D, poiché questo farà spostare i stessi nello spazio globale, richiedendo quindi di ricostruire il BVH.

Cambiare la visibilità di un OccluderInstance3D (o di uno dei suoi nodi genitore) non è un'operazione costosa in confronto, poiché l'aggiornamento deve avvenire una sola volta (anziché continuamente).

Ad esempio, se hai una porta scorrevole o girevole, è possibile fare in modo che il nodo OccluderInstance3D non sia un nodofiglio della porta stessa (in modo che l'occlusore non si muova mai), ma è possibile nascondere la visibilità dell'OccluderInstance3D una volta che la porta inizia ad aprirsi. È poi possibile mostrare nuovamente l'OccluderInstance3D una volta che la porta è completamente chiusa.

Se è assolutamente necessario spostare un nodo OccluderInstance3D durante il gioco, utilizza una forma primitiva Occluder3D anziché una forma complessa precalcolata.

Utilizza le forme di occlusore più semplici possibili

Se noti prestazioni scarse o scatti in scene 3D complesse, potrebbe significare che la CPU è sovraccaricata a causa del rendering di occlusori dettagliati. Seleziona il nodo OccluderInstance3D, aumenta la proprietà Bake > Simplification e poi riprepara gli occlusori.

Ricorda di mantenere un valore di semplificazione ragionevole. Valori troppo elevati per la geometria del livello potrebbero portare a un occlusion culling errato, come descritto in Il mio oggetto occluso viene scartato quando non dovrebbe.

Se ciò non dovesse ancora portare a un utilizzo della CPU abbastanza basso, è possibile provare a regolare l'impostazione del progetto Rendering > Occlusion Culling > Qualità di costruzione BVH e/o a diminuire Rendering > Occlusion Culling > Raggi d'occlusione per thread. Per vedere queste impostazioni, bisogna abilitare l'opzione Avanzate nella finestra Impostazioni del progetto.

Risoluzione dei problemi

Il mio oggetto occluso non è scartato quando dovrebbe esserlo

Dal lato dell'occlusore:

Innanzitutto, verifica nuovamente che la proprietà Bake > Cull Mask nell'OccluderInstance3D sia impostata in modo da consentire la preparazione delle mesh desiderate. Lo strato di visibilità dei nodi MeshInstance3D deve essere presente all'interno della maschera di culling affinché la mesh sia inclusa nella preparazione.

Si noti inoltre che la preparazione degli occlusori prende in considerazione solo le mesh con materiali opachi. Le superfici con materiali trasparenti non saranno incluse nella preparazione, anche se la texture applicata su di esse è completamente opaca.

Infine, ricorda che i nodi MultiMeshInstance3D, GPUParticles3D, CPUParticles3D e CSG non sono presi in considerazione durante la preparazione degli occlusori. Come alternativa, puoi aggiungergli i nodi OccluderInstance3D manualmente.

Dal lato dell'oggetto occluso:

Assicurati che Extra Cull Margin sia impostato al valore più basso possibile (di solito dovrebbe essere 0.0) e che Ignore Occlusion Culling sia disabilitato nella sezione GeometryInstance3D dell'oggetto.

Inoltre, verifica le dimensioni dell'AABB (rappresentate da un riquadro arancione quando selezioni il nodo). Questo riquadro deve essere completamente occluso dalle forme di occlusione affinché l'oggetto occluso sia nascosto.

Il mio oggetto occluso viene scartato quando non dovrebbe

La causa più probabile di questo problema è che gli oggetti inclusi nella preparazione degli occlusori siano stati spostati dopo la preparazione. Ad esempio, ciò può accadere quando si sposta la geometria del livello o se ne riorganizza la disposizione. Per risolvere, seleziona il nodo OccluderInstance3D e ripeti la preparazione degli occlusori.

Può accadere anche perché sono stati inclusi oggetti dinamici nella preparazione, anche se non avrebbero dovuto. Utilizza la modalità di disegno di debug dell'occlusion culling per individuare le forme di occlusione che non dovrebbero essere presenti, poi regola adeguatamente la maschera di culling per la preparazione.

L'ultima possibile causa è una semplificazione eccessivamente aggressiva delle mesh durante la preparazione degli occlusori. Seleziona il nodo OccluderInstance3D, diminuisci la proprietà Bake > Simplification e poi riprepara degli occlusori.

Come ultima speranza, è possibile abilitare la proprietà Ignore Occlusion Culling sull'oggetto occluso. Ciò annullerà i miglioramenti sulle prestazioni dovuti all'occlusion culling per quell'oggetto, ma ha senso farlo per gli oggetti che non saranno mai soggetti a culling (come ad esempio un modello visto in prima persona).