Come implementeresti l'aberrazione cromatica?


22

Come implementeresti l'effetto dell'aberrazione cromatica con gli shader?

Il rendering del mondo con distanze di messa a fuoco diverse per ciascun colore risolverebbe il problema (forse con l'uso di un solo passaggio di rendering della profondità)?


Perché vorresti implementare l'abberazione cromatica?
ashes999,

3
Potresti procedere allo stesso modo della fioritura. Dovresti combinare la tua scena normale con 3 versioni sfocate di essa; ognuna di queste tre trame dovrebbe essere tinta prevalentemente nei 3 colori di base. Naturalmente, le variazioni sono possibili se si utilizzano strategie di sfocatura diverse per le 3 trame (ad esempio la sfocatura direzionale con diversi offset angolari potrebbe fare il trucco).
teodron,

3
@ ashes999 - Forse un mirino da cecchino o un'altra lente lunga, per aggiungere un tocco di realismo? L'aberrazione cromatica è un artefatto di molti tipi di lenti composte.
KeithS,

Potresti anche voler implementare l'aberrazione cromatica per contrastare qualsiasi aberrazione causata da una lente attraverso la quale il gioco viene visualizzato. Ad esempio, è una buona idea avere aberrazione cromatica ai bordi della vista in una partita giocata con Oculus Rift.
Joseph Mansfield,

Risposte:


22

L'aberrazione cromatica si verifica quando un obiettivo non può mettere a fuoco tutti i colori sullo stesso punto focale. Un modo semplice per simulare questo effetto e renderlo come un rapido post-processo a schermo intero è applicare un offset a ciascun canale di colore in uno shader di frammenti.

Utilizzando un offset diverso per ciascun canale, è possibile ottenere un facsimile ragionevole dell'effetto desiderato. Un esempio di questa tecnica può essere trovato qui ; lo shader di frammenti sarebbe simile a questo:

void main () {
    // Previously, you'd have rendered your complete scene into a texture
    // bound to "fullScreenTexture."
    vec4 rValue = texture2D(fullscreenTexture, gl_TexCoords[0] - rOffset);  
    vec4 gValue = texture2D(fullscreenTexture, gl_TexCoords[0] - gOffset);
    vec4 bValue = texture2D(fullscreenTexture, gl_TexCoords[0] - bOffset);  

    // Combine the offset colors.
    gl_FragColor = vec4(rValue.r, gValue.g, bValue.b, 1.0);
}

Questo semplice hack non tiene davvero conto del fatto che l'aberrazione cromatica è un effetto lente, tuttavia: per ottenere una migliore simulazione, si vorrebbe effettivamente renderizzare qualcosa che funga da obiettivo. Questo è simile al modo in cui rendi gli oggetti che sono riflettenti o rifrattivi. Di conseguenza, un tipico shader di riflessione / rifrazione può essere la base per implementare l'aberrazione cromatica.

Normalmente, calcoleresti un singolo vettore di rifrazione basato su un vettore di vista e su un indice di rifrazione definito , usando la funzione di rifrazione di GLSL in uno shader di vertici:

void main () {
    // ...

    // RefractionVector is a varying vec3.
    // 'ratio' is the ratio of the two indices of refraction.
    RefractionVector = refract(incidentVector, normalVector, ratio);

    // ...
}

Quindi useresti quel vettore in uno shader di frammenti per eseguire una ricerca della trama del cubo (in una mappa ambientale). In genere questo viene fatto insieme a un effetto di riflessione e combinato usato un termine di Fresnel calcolato .

Per simulare l'aberrazione cromatica, quindi, è possibile eseguire tre diversi calcoli vettoriali di rifrazione, ciascuno leggermente sfalsato tramite diversi indici di rifrazione, nello shader di vertice:

void main () {
    // ...

    // RefractionVector is a varying vec3, as above.
    // 'ratioR,' et cetera, is the ratio of indices of refraction for
    // the red, green and blue components respectively.
    RedRefractionVector = refract(incidentVector, normalVector, ratioR);
    GreenRefractionVector = refract(incidentVector, normalVector, ratioG);
    BlueRefractionVector = refract(incidentVector, normalVector, ratioB);

    // ...
}

Questi tre diversi vettori possono essere utilizzati per eseguire tre diverse ricerche di mappe cubiche, che possono essere mescolate insieme in modo simile a come i colori sono stati miscelati nell'esempio semplice:

void main () {
    vec3 color;
    color.r = vec3(textureCube(EnvironmentMap, RedRefractionVector)).r;
    color.g = vec3(textureCube(EnvironmentMap, GreenRefractionVector)).g;
    color.b = vec3(textureCube(EnvironmentMap, BlueRefractionVector)).b;

    gl_FragColor = vec4(color, 1.0);
}

Per ulteriori dettagli, OpenGL Orange Book è disponibile e contiene un esempio degli effetti base di riflessione e rifrazione, nonché un esempio dell'effetto di aberrazione cromatica.


Esiste un approccio che utilizza solo un campione di trama e lo tinge solo? Sarebbe molto utile per applicazioni come il ray tracing, in cui il tracciamento da tre a uno è molto costoso.
Tara,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.