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