Загальний контур:
Створіть карту глибини своєї сцени без щита. Ви можете отримати це ефективно безкоштовно, оскільки прозорі об’єкти часто виводяться в пізньому проході. В іншому випадку ви можете створити карту глибини, відображаючи екран екрана sans на RTT за допомогою шейдера глибини.
Візуалізуйте сцену нормально, перенесіть карту глибини до вашої екранізації.
У шейдері обчисліть різницю глибини сцени від глибини фрагмента щита та використовуйте цю різницю для зміни кольору фрагмента.
Демо
Я написав просту демонстрацію WebGL.
Рядок за рядком
Давайте детально перейдемо до коду шейдера фрагмента:
float solidsDepth = texture2D(depthMap, gl_FragCoord.xy / dims).r;
Зробіть карту глибини на кожному фрагменті. Не забудьте розділити розміри вікна перегляду, щоб перетворити фрагмент з екранного простору [0, ширина / висота] в нормалізовані [0,0, 1,0] координати. На даний момент, якщо ви просто встановите колір фрагмента на вибірку пікселя карти глибини, це виглядатиме так:
Карта глибини має відтінки сірого, тому ви можете отримати значення з будь-якого каналу (я r
тут використовував ).
float solidsDiff = 1.0 - smoothstep(
zNear,
zFar,
gl_FragCoord.z / gl_FragCoord.w
) - solidsDepth;
Потім ви можете використовувати цей зразок глибини, щоб знайти різницю між глибиною сцени та глибиною фрагмента щита. Не забудьте також нормалізувати свою глибину, взяти її від [zNear, zFar] (найближчої та далекої площин вашої камери) до [0.0, 1.0]. smoothstep
робить це прекрасно. 1.0 -
, Щоб інвертувати значення такого , що solidsDiff
є 1,0 , коли різниця є максимальною (zFar - zNear) і 0,0 в мінімумі (0.0).
Зауважте, що я припускав, що solidsDepth
вже нормалізувався в шейдері глибини, який створив карту глибини.
float alpha = 0.3 + max(0.0, 1.0 - log(100.0 * (solidsDiff - 0.005) + 1.0));
Потім ви можете змінити альфа-канал свого екрана залежно від різниці глибини. Тут ми починаємо з мінімальної альфа 0.3
, потім створюємо приємне різке збільшення альфа, коли ми майже 0.0
різняться.
- 0.005
Зсув просто додає білий запас , щоб зробити «перетин» товщі. Спробуйте змінити його!
gl_FragColor = vec4(vec3(1.0), alpha);
І нарешті, застосуйте цю альфа до кольору фрагмента.
Аксесуари
Ви можете зробити вигнутий щит, додати плазму для вигляду "енергетичного щита" (демонстрацію) або дослідити ефекти, лише показуючи перехрестя (демонстрацію) .
Небо Ваша відеокарта - це межа!