Wie würden Sie chromatische Aberration implementieren?

22

Wie würden Sie den Effekt der chromatischen Aberration mit Shadern implementieren ?

Würde das Rendern der Welt mit unterschiedlichen Fokusentfernungen für jede Farbe das Problem lösen (möglicherweise mit der Verwendung von nur einem Tiefenrendering-Durchgang)?

Quonux
quelle
Warum sollten Sie chromatische Abberation implementieren?
Asche999
3
Sie können genauso vorgehen, wie die Blüte erreicht wird. Sie sollten Ihre normale Szene mit 3 unscharfen Versionen davon kombinieren. Jede dieser drei Texturen sollte vorwiegend in den drei Grundfarben getönt sein. Natürlich sind Variationen möglich, wenn Sie für die drei Texturen unterschiedliche Unschärfestrategien verwenden (z. B. können Richtungsunschärfen mit unterschiedlichen Winkelversätzen den Trick sein).
Teodron
3
@ ashes999 - Vielleicht ein Scharfschützenfernrohr oder eine andere lange Linse, um einen Hauch von Realismus hinzuzufügen? Die chromatische Aberration ist ein Artefakt vieler Verbundlinsendesigns.
KeithS
Möglicherweise möchten Sie auch eine chromatische Aberration implementieren, um einer Aberration entgegenzuwirken, die durch ein Objektiv verursacht wird, durch das das Spiel betrachtet wird. Zum Beispiel ist es eine gute Idee, chromatische Aberration an den Rändern der Ansicht in einem Spiel zu haben, das mit der Oculus Rift gespielt wird.
Joseph Mansfield

Antworten:

22

Eine chromatische Aberration wird verursacht, wenn ein Objektiv nicht jede Farbe auf den gleichen Brennpunkt fokussieren kann. Eine einfache Möglichkeit, diesen Effekt zu fälschen und ihn als schnellen Postprozess im Vollbildmodus wiederzugeben, besteht darin, jedem Farbkanal in einem Fragment-Shader einen Versatz zuzuweisen.

Durch die Verwendung eines anderen Offsets für jeden Kanal können Sie ein angemessenes Faksimile des gewünschten Effekts erzielen. Ein Beispiel für diese Technik finden Sie hier ; Der Fragment-Shader würde ungefähr so ​​aussehen:

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);
}

Dieser einfache Hack berücksichtigt jedoch nicht wirklich die Tatsache, dass chromatische Aberration ein Linseneffekt ist: Um eine bessere Simulation zu erhalten, möchten Sie tatsächlich etwas rendern, das als Linse fungiert. Dies ähnelt dem Rendern von reflektierenden oder refraktiven Objekten. Folglich kann ein typischer Reflexions- / Brechungs-Shader die Basis für die Implementierung der chromatischen Aberration sein.

Normalerweise würde man einen einzigen Brechungs Vektor auf einem Sichtvektor und einige definierte Basis berechnen Brechungsindex unter Verwendung von GLSL der refract Funktion in einem Vertex - Shader:

void main () {
    // ...

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

    // ...
}

Dann würden Sie diesen Vektor in einem Fragment-Shader verwenden, um eine Würfel-Textur-Suche (in eine Umgebungskarte) durchzuführen. In der Regel wird dies neben einem Reflexionseffekt durchgeführt und unter Verwendung eines berechneten Fresnel-Terms kombiniert .

Um die chromatische Aberration zu simulieren, können Sie im Vertex-Shader drei verschiedene Berechnungen des Brechungsvektors durchführen, die jeweils geringfügig über unterschiedliche Brechungsindizes versetzt sind:

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);

    // ...
}

Diese drei verschiedenen Vektoren können verwendet werden, um drei verschiedene Würfelkarten-Lookups durchzuführen, die ähnlich wie in dem einfachen Beispiel gemischt werden können:

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);
}

Für weitere Details ist das OpenGL Orange Book erhältlich. Es enthält ein Beispiel für die grundlegenden Reflexions- und Brechungseffekte sowie ein Beispiel für den Effekt der chromatischen Aberration.

Josh
quelle
Gibt es einen Ansatz, bei dem nur ein Texturmuster verwendet und nur getönt wird? Dies ist sehr vorteilhaft für Anwendungen wie die Strahlverfolgung, bei denen die Verfolgung von drei gegen einen Strahl sehr teuer ist.
Tara