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.