Comment mettriez-vous en œuvre l'aberration chromatique?

22

Comment mettriez-vous en œuvre l'effet de l'aberration chromatique avec des shaders?

Le rendu du monde avec des distances de mise au point différentes pour chaque couleur résoudrait-il le problème (peut-être avec l'utilisation d'une seule passe de rendu en profondeur)?

Quonux
la source
Pourquoi voudriez-vous mettre en œuvre l'abberation chromatique?
ashes999
3
Vous pouvez procéder de la même manière que la floraison est atteinte. Vous devez combiner votre scène normale avec 3 versions floues; chacune de ces trois textures doit être principalement teintée dans les 3 couleurs de base. Bien sûr, des variations sont possibles si vous utilisez différentes stratégies de flou pour les 3 textures (par exemple, un flou directionnel avec différents décalages angulaires pourrait faire l'affaire).
teodron
3
@ ashes999 - Peut-être une lunette de tireur d'élite ou un autre objectif long, pour ajouter une touche de réalisme? L'aberration chromatique est un artefact de nombreuses conceptions de lentilles composées.
KeithS
Vous pouvez également vouloir implémenter l'aberration chromatique pour contrer toute aberration causée par un objectif à travers lequel le jeu est visualisé. Par exemple, c'est une bonne idée d'avoir une aberration chromatique sur les bords de la vue dans un jeu joué avec l'Oculus Rift.
Joseph Mansfield

Réponses:

22

L'aberration chromatique est causée lorsqu'un objectif ne peut pas focaliser chaque couleur sur le même point focal. Un moyen simple de simuler cet effet et de le rendre en tant que post-traitement plein écran rapide consiste à appliquer un décalage à chaque canal de couleur dans un shader de fragment.

En utilisant un décalage différent pour chaque canal, vous pouvez obtenir un fac-similé raisonnable de l'effet souhaité. Un exemple de cette technique peut être trouvé ici ; le fragment shader ressemblerait à ceci:

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

Ce simple hack ne prend pas vraiment en compte le fait que l'aberration chromatique est un effet d'objectif, cependant: pour obtenir une meilleure simulation, vous voudriez réellement rendre quelque chose pour agir comme l'objectif. Ceci est similaire à la façon dont vous effectuez le rendu d'objets réfléchissants ou réfringents. Par conséquent, un shader de réflexion / réfraction typique peut être la base de la mise en œuvre de l'aberration chromatique.

Normalement, vous devriez calculer un seul vecteur de réfraction basé sur un vecteur de vue et certains défini indice de réfraction , en utilisant de GLSL réfractent fonction dans un vertex shader:

void main () {
    // ...

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

    // ...
}

Ensuite, vous utiliseriez ce vecteur dans un shader de fragment pour effectuer une recherche de texture de cube (dans une carte d'environnement). En règle générale, cela se fait parallèlement à un effet de réflexion, et combiné utilisé un terme de Fresnel calculé .

Pour simuler l'aberration chromatique, vous pouvez alors effectuer trois calculs de vecteur de réfraction différents , chacun légèrement décalé via différents indices de réfraction, dans le vertex shader:

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

    // ...
}

Ces trois vecteurs différents peuvent être utilisés pour effectuer trois recherches de carte de cube différentes, qui peuvent être mélangées de la même manière que les couleurs ont été mélangées dans l'exemple simple:

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

Pour plus de détails, l' OpenGL Orange Book est disponible et contient un exemple des effets de réflexion et de réfraction de base, ainsi qu'un exemple de l'effet d'aberration chromatique.


la source
Existe-t-il une approche qui utilise un seul échantillon de texture et ne teinte que cela? Il serait très avantageux pour des applications comme le lancer de rayons, où le suivi de trois contre un rayon est très coûteux.
Tara