Uno schema generale:
Crea una mappa di profondità della tua scena senza lo scudo. Puoi ottenerlo in modo efficace gratuitamente, poiché gli oggetti trasparenti sono spesso resi in un passaggio successivo comunque. Altrimenti, è possibile creare la mappa della profondità eseguendo il rendering della scena senza scudo su un RTT con uno shader di profondità.
Rendi la tua scena normalmente, passa la mappa della profondità al tuo shader scudo.
Nello shader, calcola la differenza nella profondità della scena dalla profondità del frammento di scudo e usa quella differenza per modificare il colore del frammento.
dimostrazione
Ho scritto una semplice demo WebGL di questo.
Linea per linea
Analizziamo in dettaglio il codice dello shader di frammenti:
float solidsDepth = texture2D(depthMap, gl_FragCoord.xy / dims).r;
Campiona la mappa di profondità in ogni frammento. Ricorda di dividere per le dimensioni della finestra per convertire il frammento dallo spazio dello schermo [0, larghezza / altezza] in coordinate [0.0, 1.0] normalizzate. A questo punto, se si imposta semplicemente il colore del frammento sul pixel della mappa di profondità campionato, sarebbe simile al seguente:
La mappa di profondità è in scala di grigi, quindi puoi ottenere il valore da qualsiasi canale (ho usato r
qui).
float solidsDiff = 1.0 - smoothstep(
zNear,
zFar,
gl_FragCoord.z / gl_FragCoord.w
) - solidsDepth;
È quindi possibile utilizzare quel campione di profondità per trovare la differenza tra la profondità della scena e la profondità del frammento dello scudo. Ricorda di normalizzare anche la tua profondità, per portarla da [zNear, zFar] (i piani vicino e lontano della tua fotocamera) a [0.0, 1.0]. smoothstep
lo fa bene. Il 1.0 -
è invertire il valore tale chesolidsDiff
è 1,0 quando la differenza è il massimo (zFar - zNear) e 0,0 al minimo (0,0).
Si noti che ho supposto che solidsDepth
fosse già normalizzato nello shader di profondità che ha creato la mappa di profondità.
float alpha = 0.3 + max(0.0, 1.0 - log(100.0 * (solidsDiff - 0.005) + 1.0));
È quindi possibile modificare il canale alfa dello scudo in base alla differenza di profondità. Qui iniziamo con un minimo di alfa di 0.3
, quindi creiamo un piacevole aumento marcato dell'alfa quando ci avviciniamo alla 0.0
differenza.
L' - 0.005
offset aggiunge solo un margine bianco per rendere più "incrocio" più spesso. Prova a modificarlo!
gl_FragColor = vec4(vec3(1.0), alpha);
E infine, applica quell'alfa al colore del tuo frammento.
miglioramenti
Potresti creare uno scudo curvo, aggiungere plasma per un aspetto "scudo di energia" (demo) o esplorare gli effetti con solo le intersezioni che mostrano (demo) .
Il cielo La tua scheda grafica è il limite!