Як би ви реалізували хроматичну аберацію?


22

Як би ви реалізували ефект хроматичної аберації за допомогою шейдерів?

Чи вирішила б візуалізація світу з різними відстанями фокусування для кожного кольору проблемою (можливо, із застосуванням лише одного пропускання глибинної передачі)?


Чому б ви хотіли реалізувати хроматичну аббацію?
ashes999

3
Можна діяти так само, як досягається цвітіння. Ви повинні поєднати свою звичайну сцену з 3 розмитими її версіями; кожну з цих трьох текстур слід тонувати переважно в 3 основні кольори. Звичайно, можливі варіації, якщо для трьох текстур використовуються різні стратегії розмивання (наприклад, фокус із розмитим кутом з різними кутовими зміщеннями може зробити трюк).
теодрон

3
@ ashes999 - Можливо, снайперський приціл чи інша довга лінза, щоб додати нотку реалізму? Хроматична аберація є артефактом багатьох складних конструкцій лінз.
KeithS

Ви також можете застосувати хроматичну аберацію для протидії будь-якій аберації, спричиненій лінзою, через яку переглядається гра. Наприклад, в грі, що грає з Oculus Rift, є кращою ідеєю мати хроматичну аберацію по краях виду.
Джозеф Менсфілд

Відповіді:


22

Хроматична аберація виникає, коли лінза не може фокусувати кожен колір до однієї фокусної точки. Простий спосіб підробити цей ефект і зробити його як швидкий повний екран після обробки - застосувати зміщення до кожного каналу кольорів у фрагменті шейдера.

Використовуючи різний зміщення для кожного каналу, ви можете досягти розумного факсиміле потрібного ефекту. Приклад цієї методики можна знайти тут ; фрагмент шейдер буде виглядати приблизно так:

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 доступна і містить приклад основних ефектів відбиття та заломлення, а також приклад ефекту хроматичної аберації.


Чи існує підхід, який використовує лише один зразок текстури і просто підфарбовує його? Це було б дуже вигідно для таких додатків, як трасування променів, де відстежувати три проти одного променя дуже дорого.
Тара
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.