Como você implementaria a aberração cromática?

22

Como você implementaria o efeito da aberração cromática com shaders?

A renderização do mundo com diferentes distâncias de foco para cada cor resolveria o problema (talvez com o uso de apenas uma passagem de renderização em profundidade)?

Quonux
fonte
Por que você deseja implementar a aberração cromática?
precisa saber é o seguinte
3
Você pode proceder da mesma maneira que a flor é alcançada. Você deve combinar sua cena normal com 3 versões borradas; cada uma dessas três texturas deve ser pintada predominantemente nas três cores básicas. É claro que são possíveis variações se você usar diferentes estratégias de desfoque para as três texturas (por exemplo, desfoque direcional com diferentes desvios angulares pode ajudar).
Teodron #
3
@ ashes999 - Talvez uma mira de atirador de elite ou outra lente longa, para adicionar um toque de realismo? A aberração cromática é um artefato de muitos designs de lentes compostas.
Keiths
Você também pode implementar a aberração cromática para combater qualquer aberração causada por uma lente através da qual o jogo está sendo visualizado. Por exemplo, é uma boa idéia ter uma aberração cromática nas bordas da vista em um jogo jogado com o Oculus Rift.
31813 Joseph Mansfield

Respostas:

22

A aberração cromática é causada quando uma lente não consegue focar todas as cores no mesmo ponto focal. Uma maneira simples de falsificar esse efeito e renderizá-lo como um pós-processo rápido em tela cheia, é aplicar um deslocamento a cada canal de cores em um sombreador de fragmento.

Usando um deslocamento diferente para cada canal, você pode obter um fac-símile razoável do efeito desejado. Um exemplo dessa técnica pode ser encontrado aqui ; o shader de fragmento ficaria assim:

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

Esse simples hack realmente não leva em conta o fato de que a aberração cromática é um efeito de lente: para obter uma simulação melhor, você realmente deseja renderizar algo para agir como a lente. É semelhante à maneira como você renderiza objetos refletivos ou refrativos. Consequentemente, um sombreador típico de reflexão / refração pode ser a base para implementar a aberração cromática.

Normalmente, você calcula um único vetor de refração com base em um vetor de visualização e em algum índice definido de refração , usando a função refract do GLSL em um shader de vértice:

void main () {
    // ...

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

    // ...
}

Em seguida, você usaria esse vetor em um shader de fragmento para executar uma pesquisa de textura de cubo (em um mapa do ambiente). Normalmente, isso é feito juntamente com um efeito de reflexão, e combinados usaram um termo de Fresnel calculado .

Para simular a aberração cromática, você pode executar três cálculos vetoriais de refração diferentes , cada um ligeiramente compensado por diferentes índices de refração, no sombreador de vértices:

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

    // ...
}

Esses três vetores diferentes podem ser usados ​​para executar três pesquisas diferentes de mapas de cubos, que podem ser combinadas de maneira semelhante à maneira como as cores foram misturadas no exemplo simples:

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

Para mais detalhes, o OpenGL Orange Book está disponível e contém um exemplo dos efeitos básicos de reflexão e refração, bem como um exemplo do efeito de aberração cromática.

Josh
fonte
Existe uma abordagem que usa apenas uma amostra de textura e apenas a tinge? Seria muito benéfico para aplicações como rastreamento de raios, onde o rastreamento de três contra um raio é muito caro.
Tara