Как мы и обещали, по ссылке код шейдера и маленькая демка, в которой можно поиграться с его настройками.
https://kovnir.github.io/sandman/Demos/GhostFlask
Это простой двухпроходный шейдер.
Первый проход (ZTest Greater) - пиксель отрисовывается, если расстояние от объекта в координате этого пикселя до камеры больше, чем значение в ZBuffer, то есть наш объект чем-то загорожен.
Второй проход (ZTest LEqual) - если расстояние до пикселя меньше или равно значению из ZBuffer. То есть как обычная отрисовка.
Вершинные шейдеры полностью идентичны:
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.normal = UnityObjectToWorldNormal(v.normal);
o.viewDir = normalize(WorldSpaceViewDir(v.vertex));
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
Трансформируем координаты и нормали, считаем направление от точки до камеры, трансформируем UV координаты, чтобы работал тайлинг.
Фрагментные шейдеры - тоже идентичны, за одним исключением - в первом проходе используется цвет из свойства _BlockedColor (в игре красный), во втором - _NormalColor (светло-желтый). Для примера будем рассматривать второй.
Первая строчка:
float alpha = 1 - dot(i.normal, i.viewDir);
Скалярное произведение между вектором направления к камере и нормалью в данном случаем показывает, как сильно схожи углы этих векторов. 1 - если они смотрят в одну сторону, 0 - если угол 90 градусов, -1 - если в разные (такого не будет, так как эта геометрия будет отсечена). Вычитаем это значение из единицы, чтобы получить обратный эффект. Впоследствии, это будет наша альфа - края объекта, как самые отвернутые от камеры будут видны отлично, а полигоны, которые смотрят на нас видно не будет. Получается отличный эффект привидений - классический “ghost shader” из многих игр.
Вторая строчка:
float alphaFactor = tex2D(_MainTex, i.uv + _Time.gg * _FogSpeed).b + _AlphaAddition;
Сдвигаем текстуру на время со скоростью _FogSpeed и берем любой канал (в данном случае голубой). Прибавляем _AlphaAddition, чтобы в местах, где b-компонента равна нулю, пиксели были не полностью прозрачными.
Следующая строчка:
_NormalColor.a = alpha * alphaFactor * _Multiplier * _Animation;
Перемножаем полученные результаты и записываем значение в альфа-канал выходного цвета. Умножаем все это на _Multiplier, чтобы контролировать прозрачность. В конце умножаем на _Animation, чтобы задавать анимацию появления/исчезновения, плавно изменяя это значение от нуля к одному и наоборот.
Последнюя строчка объяснения не требует:
return _NormalColor;
В общем, это все. Если есть какие-то вопросы - пишите в комментарии.
#gamedev #indiegame #indiedev #indiegamedev #lowpoly #madewithunity #mwu #sandman #TTN #ThroughTheNightmares #unitytips