Общий план:
Создайте карту глубины вашей сцены без щита. Вы можете получить это эффективно бесплатно, так как прозрачные объекты часто отображаются на более поздних этапах. В противном случае вы можете создать карту глубины, отрисовав сцену без щита на 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);
И наконец, примените эту альфу к цвету вашего фрагмента.
Улучшения
Вы можете сделать изогнутый щит, добавить плазму для «энергетического щита» (демо) или исследовать эффекты, показывая только пересечения (демо) .
Небо Ваша видеокарта это предел!