Я хотел посмотреть, смогу ли я осуществить это без динамической регенерации сетки для водопада каждый кадр. Оказывается, есть способ. : D
Каждый объект, который может блокировать водопад (объекты, на которых есть WaterCatcher
сценарий в моем прототипе), имеет контурную сетку, охватывающую его периметр. (Это может быть автоматически сгенерировано заранее, используя форму коллайдера)
Эта контурная сетка отображает поток воды вдоль объекта. Я использую шейдер, чтобы clip
вывести часть, которая находится под объектом. Я также отслеживаю левую и правую точки «ловли», где водопад приземляется на объект и течет влево или вправо соответственно, поэтому я могу clip
выделить часть, которая находится слева от правого водопада и справа от левого водопада.
Тогда вертикальные падения - это просто базовые четырехъядерные примитивы, вытянутые до соответствующей длины. Я использую другой шейдер, чтобы прокрутить текстуру водопада над водопадом и затемнить ее сверху и снизу. Затем я наношу на систему частиц пены в точке удара, чтобы помочь покрыть смесь.
Вот крупный план, чтобы вы могли видеть составные части.
На вершине у меня есть «корневой» водопад, чтобы начать что-то новое. Каждый кадр, после Update()
запуска всех сценариев, чтобы перемещать вещи, запускается CircleCast
вниз, чтобы увидеть, попадает ли его вода в что-нибудь. Если он ударяется о WaterCatcher
, он говорит ему показать свою водную оболочку ниже по течению от точки попадания.
Я определяю «вниз по течению», используя нормальное попадание - если оно очень близко к вертикали или если входящий водопад охватывает грани, которые имеют наклон в обоих направлениях, то мы проливаем как влево, так и вправо.
У каждого WaterCatcher
есть свой левый и правый водопад, который он включает и размещает на своем дальнем краю, если он проливается в этом направлении - в противном случае они остаются скрытыми. Эти водопады в свою очередь CircleCast
обрушиваются вниз, чтобы найти то, на что они проливаются, и так далее ...
В прототипе все еще есть несколько визуальных сбоев, которые можно улучшить - поток воды вдоль объекта внезапно всплывает вместо анимации, а в правилах потока может использоваться немного больше допусков или гистерезиса, поэтому его не так легко отключить. вращающиеся объекты. Я думаю, что это должны быть довольно решаемые проблемы.
Фон, камни и текстуры вращающейся платформы через Кенни
Вот приемы, которые я использую в своем фрагментном шейдере для улавливания воды:
// My wraparound geometry is build so the "x+" UV direction
// points "outward" from the object.
// Using derivatives, I can turn this into a vector in screen space.
// We'll use this below to clip out water hanging off the bottom.
float2 outward = float2(ddx(i.uv.x), ddy(i.uv.x));
// i.worldX is the worldspace x position of this fragment
// (interpolated from the vertex shader)
// _LeftX is a material property representing the worldspace x coordinate
// of the rightmost water flow that's spilling left,
// and _RightX the wold x of the leftmost water flow that's spilling right.
float left = _LeftX - i.worldX; // +ve if we're to the left of a left spill.
float right = i.worldX - _RightX; // +ve if we're to the right of a right spill.
float limit = max(left, right); // +ve if we're in the path of either flow.
// If the "outward" vector is pointing down, make this negative.
limit = min(limit, outward.y + 0.001f);
// If any of the conditions above make limit <= 0, abort this fragment.
clip(limit);
// Otherwise, scroll the water texture!
// Counter-clockwise if we're in the left flow, clockwise otherwise.
i.uv.y -= sign(left) * _Time.y;