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à)?
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à)?
Risposte:
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.