Як би ви реалізували ефект хроматичної аберації за допомогою шейдерів?
Чи вирішила б візуалізація світу з різними відстанями фокусування для кожного кольору проблемою (можливо, із застосуванням лише одного пропускання глибинної передачі)?
Як би ви реалізували ефект хроматичної аберації за допомогою шейдерів?
Чи вирішила б візуалізація світу з різними відстанями фокусування для кожного кольору проблемою (можливо, із застосуванням лише одного пропускання глибинної передачі)?
Відповіді:
Хроматична аберація виникає, коли лінза не може фокусувати кожен колір до однієї фокусної точки. Простий спосіб підробити цей ефект і зробити його як швидкий повний екран після обробки - застосувати зміщення до кожного каналу кольорів у фрагменті шейдера.
Використовуючи різний зміщення для кожного каналу, ви можете досягти розумного факсиміле потрібного ефекту. Приклад цієї методики можна знайти тут ; фрагмент шейдер буде виглядати приблизно так:
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);
}
Цей простий злом насправді не враховує той факт, що хроматична аберація є ефектом лінзи: для кращого моделювання ви насправді хочете зробити щось, що виступає лінзою. Це схоже на те, як ви відображаєте відображаючі або заломлюючі об'єкти. Отже, типовий шейдер відбиття / заломлення може бути основою для здійснення хроматичної аберації.
Як правило, ви б обчислити один вектор рефракції на основі вектора виду і деякі певний показник заломлення , з використанням GLSL в заломлювати функцію в вершинних шейдеров:
void main () {
// ...
// RefractionVector is a varying vec3.
// 'ratio' is the ratio of the two indices of refraction.
RefractionVector = refract(incidentVector, normalVector, ratio);
// ...
}
Потім ви використовуєте цей вектор у шейдері фрагмента, щоб здійснити пошук текстури куба (на карту навколишнього середовища). Зазвичай це робиться поряд з ефектом відображення, а також у поєднанні використовується обчислюваний термін Френеля .
Щоб імітувати хроматичну аберацію, тоді у вершинній шейдері можна виконати три різні обчислення вектора заломлення, кожне з яких трохи зміщене за допомогою різних показників заломлення:
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);
// ...
}
Ці три різні вектори можуть бути використані для виконання трьох різних пошукових карт кубів, які можна змішати разом, аналогічно змішуванню кольорів у простому прикладі:
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);
}
Для отримання більш детальної інформації помаранчева книга OpenGL доступна і містить приклад основних ефектів відбиття та заломлення, а також приклад ефекту хроматичної аберації.