
Diablo Immortal è un gioco di ruolo d'azione multiplayer free-to-play (ARPG) sviluppato in collaborazione da Blizzard Entertainment e NetEase. Diablo Immortal, un nuovo capitolo della serie Diablo, lanciato nel 2022. Il gioco colma la lacuna narrativa tra Diablo 2 e Diablo 3 e presenta una nuova avventura intorno ai frammenti della Pietra del Mondo, in cui i giocatori esplorano il continente di Sanctuary per combattere contro demoni e forze corrotte.
Grazie all'innovazione dell'architettura GPU mobile e alle innovazioni nelle funzionalità di accelerazione hardware, la tecnologia di ray tracing sta gradualmente migrando dai computer ai dispositivi mobili, diventando uno dei fattori chiave del rendering grafico ad alta fedeltà. Il calcolo di riflessi dinamici realistici dal punto di vista fisico è computazionalmente impegnativo, ma un'unità hardware dedicata lo rende possibile su piattaforme mobile con limitazioni di potenza. Tracceggiato il percorso di propagazione della luce attraverso la scena in tempo reale, la tecnologia simula con precisione il comportamento riflettente di superfici complesse come specchi, metalli e liquidi. Il ray tracing supera le limitazioni spaziali e gli errori di approssimazione degli schemi di rasterizzazione tradizionali e supporta l'espressione coerente a livello globale di sorgenti di luce dinamiche, oggetti off-screen e riflessi a più livelli.
Ray tracing hardware sui dispositivi mobili
La tecnologia di ray tracing hardware include principalmente due paradigmi di implementazione: pipeline di ray tracing e query ray.
La pipeline di ray tracing crea una pipeline completa tramite fasi shader dedicate (generazione di raggi / intersezione / shader di hit più vicino). Sebbene possa ottenere un controllo preciso dell'interazione dei raggi, la pipeline di ray tracing richiede una configurazione indipendente della pipeline, il che aumenta la complessità dello sviluppo.
Le query sui raggi, invece, consentono di avviare query sui raggi direttamente dagli shader di calcolo o frammento tradizionali, rendendola una tecnologia di base per il ray tracing mobile. Eliminando la necessità di pipeline separate, Ray Query non solo semplifica notevolmente il processo di sviluppo, ma offre anche tre vantaggi principali:
- Fornisce compatibilità con ambienti di calcolo eterogenei e hardware di ray tracing non completo
- Supporta l'invocazione on demand del ray tracing in qualsiasi fase di ombreggiatura
- Riducendo l'utilizzo delle risorse, soddisfa le limitazioni di larghezza di banda e potenza delle piattaforme mobile e fornisce una base fattibile per effetti avanzati come l'illuminazione globale dinamica e il riflesso in tempo reale nei giochi mobile
Diablo Immortal utilizza Vulkan per sfruttare le funzionalità di ray tracing hardware della GPU. Il gioco calcola il percorso dei raggi di luce tramite la scena in tempo reale e tiene conto di proprietà dei materiali complesse per ottenere effetti di riflessione in tempo reale rivoluzionari sui dispositivi Android.


Struttura di accelerazione
La struttura di accelerazione è il nucleo del ray tracing hardware. La struttura di accelerazione migliora notevolmente l'efficienza dei test di intersezione dei raggi tramite l'organizzazione gerarchica dei dati.
In genere, il sistema ha due livelli: la struttura di accelerazione di primo livello (TLAS) e la struttura di accelerazione di livello inferiore (BLAS):
- TLAS svolge il ruolo di gestore di scene: registrando la matrice di trasformazione spaziale (inclusa posizione, rotazione e scala) di tutte le istanze BLAS, TLAS realizza l'organizzazione globale delle scene dinamiche. Ad esempio, TLAS consente agli sviluppatori di distribuire centinaia di istanze dello stesso modello di albero in posizioni e pose diverse nella scena. Pertanto, gli sviluppatori devono solo aggiornare la matrice di trasformazione dell'oggetto in movimento in ogni fotogramma anziché ricostruire la geometria.
- BLAS come unità di base: responsabile della codifica efficiente dei dettagli geometrici di un singolo oggetto 3D, BLAS stabilisce una struttura di indice spaziale tramite l'algoritmo BVH (bounding volume hierarchy) in modo che le aree irrilevanti possano essere saltate rapidamente durante il rilevamento dei raggi.
Questo design gerarchico consente alla pipeline di ray tracing di formare una catena di rilevamento efficiente di ray ==> TLAS (istanza di oggetto setaccio approssimativo) ==> BLAS (intersezione esatta).
Separare i modelli dinamici e statici è fondamentale per ridurre al minimo il costo della costruzione della struttura di accelerazione:
- Modello statico: il BLAS deve essere creato una sola volta nella fase di inizializzazione e può essere riutilizzato direttamente nel caricamento delle scene successive. Per evitare il ritardo di caricamento delle scene di grandi dimensioni, la tecnologia di precostruzione asincrona del framing può essere utilizzata per distribuire l'attività di costruzione BLAS su più frame.
- Modello dinamico
- In base all'animazione scheletrica: i dati dei vertici con skin devono essere calcolati in parallelo dall'shader di calcolo ogni frame per generare un nuovo buffer di vertici e quindi attivare l'aggiornamento incrementale del BLAS corrispondente, evitando così la ricostruzione completa per migliorare le prestazioni.
- Trasformazione del corpo rigido: se sono coinvolte solo trasformazioni di traslazione/rotazione/zoom, non è necessario modificare BLAS, ma solo aggiornarne la matrice di trasformazione del mondo in TLAS e attivare la procedura di aggiornamento rapido di TLAS.
La ricostruzione periodica è essenziale per mantenere l'efficienza della struttura di accelerazione nelle scene dinamiche con il ray tracing. Quando gli oggetti dinamici subiscono modifiche significative nella topologia geometrica, ad esempio deformazioni o spostamenti di vertici su larga scala, la suddivisione spaziale originale potrebbe non riuscire, riducendo il rendimento del rilevamento delle collisioni durante il percorso del raggio. Di conseguenza, deve essere attivata una ricostruzione completa, anziché un aggiornamento incrementale, delle matrici BLAS/TLAS altamente dinamiche ogni N frame.
Infine, per ottimizzare il rendimento del rendering con il ray tracing, adotta una strategia di costruzione dinamica del TLAS in base alla regione visibile del personaggio: solo i modelli all'interno della soglia del raggio attivo del personaggio sono inclusi nel TLAS per ridurre il sovraccarico del calcolo dell'intersezione dei raggi.
Riflessi con ray tracing
Le riflessioni con ray tracing hanno diversi vantaggi rispetto alle tecniche tradizionali come le riflessioni nello spazio schermo (SSR) e le riflessioni piane (superfici semplici che proiettano una scena in una dimensione). La riflessione con ray tracing simula fisicamente il percorso della luce, acquisisce con precisione gli oggetti dinamici all'interno e all'esterno della scena, supporta le riflessioni naturali da superfici curve e non piane e consente più effetti di rimbalzo della luce, come gli specchi. Al contrario, la SSR è limitata alle informazioni visibili sullo schermo e i riflessi piatti e planari sono soggetti a errori visivi o distorsioni in scene complesse.


In linea di principio, la riflessione con ray tracing è simile alla SSR tradizionale: emette raggi in direzione della riflessione della linea di vista su una base pixel per pixel e calcola l'intersezione dei raggi con gli oggetti della scena. Il punto di intersezione restituito dall'API di query sui raggi contiene informazioni geometriche (inclusi ID istanza, indice geometria e indice primitivo) e parametri di rasterizzazione (coordinate baricentriche) a livello di triangolo, ma non contiene dati sul colore dei pixel. La soluzione tipica utilizza la tecnologia di associazione delle risorse senza vincoli per precompilare tutti i parametri di texture e materiale della scena in un array di indici globali. Utilizzando gli identificatori geometrici restituiti dalla query sui raggi, è possibile cercare le proprietà fisiche del materiale corrispondente (come la mappa normale e la ruvidità) e combinarle con l'interpolazione delle coordinate baricentriche per calcolare le informazioni sull'ombreggiatura della superficie e il valore di colore reale dell'intersezione può essere ricostruito tramite la rasterizzazione.
Tuttavia, durante il processo di implementazione, il team di Diablo Immortal ha scoperto due problemi tecnici significativi:
- Il modello di illuminazione è stato forzato a essere unificato, il che è in conflitto con i diversi sistemi di ombreggiatura accumulati nella cronologia del progetto e comporterebbe una mancata corrispondenza tra il materiale speculare e il materiale originale.
- La varietà di formati dei vertici comporta il degrado dell'efficienza dei rami di istruzioni nella fase di rasterizzazione, che è un problema importante nel bilancio delle prestazioni limitato del dispositivo mobile.
Il team di Diablo Immortal ha introdotto in modo innovativo il buffer di visibilità per separare l'elaborazione della geometria dai calcoli di ombreggiatura:
- Fase di ray tracing: le informazioni sugli impatti dei raggi a livello di pixel vengono acquisite in tempo reale tramite la query sui raggi. L'identificatore spaziale 3D (
InstanceID
conPrimitiveIndex
) del punto di intersezione viene codificato in un ID visibilità compatto e scritto nel buffer dello spazio dello schermo. - Fase di colorazione: in modo simile alle operazioni eseguite dagli shader vertex e pixel, gli identificatori geometrici nel buffer di visibilità vengono analizzati dinamicamente, le proprietà vertex (come UV e normali) e le mappe dei materiali basate sulla fisica del modello originale vengono recuperate e infine vengono eseguiti i calcoli di ombreggiatura associati al tipo di materiale.
Questa soluzione consente di collegare gli asset artistici al sistema di riflessioni con ray tracing senza dover modificare gli shader o i formati dei vertici.
Passaggi di rendering specifici
Passaggio della query sui raggi
Corrisponde alla fase di ray tracing e genera un buffer di visibilità per le riflessioni nello spazio dello schermo:
- Colore0
- Formato: R32G32UInt
- R = TriangleID,G = Barycentrics

- Profondità:
- Formato: Profondità32F
- D = EncodeAsFloat(InstanceIdx, GeometryIdx)
- L'identificatore del materiale dell'intersezione viene codificato in virgola mobile di 32 bit e scritto nel buffer di profondità per la fase successiva della tecnica di rilevamento della corrispondenza della codifica della profondità del materiale

Rispetto al compute shader, la query sui raggi nel pixel shader presenta i seguenti vantaggi:
- Integrazione della pipeline: la pipeline è incorporata direttamente nelle pipeline di rendering forward/differito esistenti, mantenendo la continuità dello stato della pipeline di rendering.
- Ottimizzazione della larghezza di banda mobile: per l'architettura mobile basata su riquadri,
la compressione senza perdita di dati on-chip può essere attivata quando i dati relativi agli impatti dei raggi vengono scritti in
RenderTarget
, riducendo il consumo di larghezza di banda della memoria rispetto all'output dello shader di calcolo tradizionale nel buffer. - Controllo della quantità di raggi: le aree non riflettenti possono essere contrassegnate e rifiutate tramite una fase di precalcolo in combinazione con un test di stencil.
Risolvere il problema
Nella fase di colorazione (vedi Riflessi con ray tracing), il team di Diablo Immortal ha ottenuto una rapida corrispondenza di identificazione utilizzando l'unità hardware del test di profondità ed eseguendo la colorazione dei materiali in batch successivi.
Per ogni materiale viene emesso un passaggio di disegno a schermo intero. Lo shader vertex ricostruisce dinamicamente l'identificatore codificato del materiale corrente. Con il test di profondità uguale, l'identificatore viene confrontato con i valori codificati nel buffer profondità e vengono conservati solo i pixel i cui valori codificati corrispondono esattamente, ovvero i pixel che appartengono all'istanza materiale corrente. I pixel mantenuti eseguono lo shader del materiale corrispondente.
Successivamente, la riproduzione di materiali ad alta precisione viene implementata nel pixel shader:
- Decodifica dei dati geometrici: estrae l'identificatore del triangolo (
MeshID
+PrimitiveID
) e le coordinate baricentriche dal buffer di visibilità e carica dinamicamente gli attributi dei vertici (posizione, UV, normale e così via) del triangolo corrispondente dal buffer dei vertici. Poiché ogni modello è ombreggiato come materiale indipendente, non sono necessarie funzionalità avanzate come la rilegatura. - Ricostruzione dei parametri della superficie: calcola le coordinate UV all'intersezione utilizzando l'interpolazione delle coordinate baricentriche. Viene eseguita la rasterizzazione software per campionare la mappa in base alle UV interpolate.
- Riutilizzo del calcolo dell'ombreggiatura: riutilizza direttamente il codice shader esistente per mantenere la stessa logica del materiale della pipeline di rendering principale.

Infine, i modelli che partecipano effettivamente al calcolo delle riflessioni rappresentano solo una parte molto piccola della scena. I dati di identificazione del modello di riflessione restituiti dalla GPU possono essere letti in modo asincrono per eliminare i modelli/materiali che non partecipano alla riflessione, riducendo efficacemente il numero di chiamate di disegno (una chiamata di disegno si verifica quando i materiali e una mesh vengono inviati alla GPU per il disegno) nella fase di ombreggiatura.
Riflessione speculare basata sulla fisica
Per ottenere riflessi ad alta fedeltà, le superfici riflettenti sono classificate come uno di tre tipi in base alla ruvidità:
- Nessuna riflessione: i calcoli delle riflessioni per queste superfici possono essere ignorati per risparmiare risorse. Se la superficie è molto ruvida, il riflesso diventa sfocato e sbiadito, quindi il contributo non è evidente.
- Riflesso allo specchio: come uno specchio liscio, l'immagine riflessa è chiara e non sfocata. Scatta la foto direttamente nella direzione della riflessione rispetto alla linea di vista.
- Riflessione lucida: la riflessione con una certa ruvidità della superficie viene simulata in base al campionamento con importanza GGX, che può tenere conto sia dell'efficienza computazionale sia dell'accuratezza fisica. La riflessione devia verso la direzione principale della riflessione speculare durante l'emissione della linea, il che migliora l'efficienza del campionamento dell'area di illuminazione.
Per ottenere una qualità delle immagini utilizzabile con un consumo energetico limitato, il team di Diablo Immortal ha adottato una soluzione 1SPP+Denoiser. In altre parole, il team di Diablo Immortal ha acquisito un campione per pixel,quindi è stato utilizzato un algoritmo di riduzione del rumore temporale/spaziale per attenuare la grande quantità di rumore introdotta dalla bassa frequenza di campionamento.
Il team di Diablo Immortal ha scelto il Reflection Denoiser in AMD FidelityFX Denoiser, un denoiser ad alte prestazioni ottimizzato per le riflessioni con ray tracing e le riflessioni nello spazio dello schermo. Il vantaggio principale di Reflection Denoiser è l'algoritmo di riduzione del rumore ibrido spazio-temporale del denoiser: combinando il frame corrente e i dati dei frame storici (in base alla compensazione del movimento), con tecniche di filtrazione spaziale (come il filtro di conservazione degli spigoli basato sulla varianza), Reflection Denoiser elimina in modo efficiente il rumore e produce effetti di riflessione uniformi a un campionamento molto basso.
Per adattarsi alle caratteristiche delle pipeline di rendering sviluppate autonomamente e soddisfare i rigidi vincoli di prestazioni dei dispositivi mobili, il team di Diablo Immortal ha implementato un'ottimizzazione mirata e un adattamento dell'architettura durante l'integrazione di AMD FidelityFX Reflection Denoiser.
Ray tracing ad alta fedeltà con Vulkan
Diablo Immortal funziona su una vasta gamma di dispositivi Android compatibili con Vulkan, in cui il team di Diablo Immortal ha sfruttato le innovative funzionalità di ray tracing hardware della GPU. Vulkan ha ridotto le complessità e le difficoltà di sviluppo, facilitando la pubblicazione di contenuti e gameplay di Diablo Immortal di alta qualità per gli utenti Android.