Volevo vedere se potevo farlo senza rigenerare dinamicamente la mesh per la cascata ogni frame. Si scopre, c'è un modo. : D
Ogni oggetto che può bloccare la cascata (oggetti che portano un WaterCatcher
copione nel mio prototipo) ha una maglia di contorno che avvolge il suo perimetro. (Questo può essere generato automaticamente in anticipo usando la forma del collider)
Questa maglia di contorno rende l'acqua che scorre lungo l'oggetto. Uso uno shader per clip
estrarre la parte che si trova sotto l'oggetto. Traccio anche un punto di "cattura" sinistro e destro in cui una cascata atterra sull'oggetto e scorre rispettivamente a sinistra oa destra, in modo da poter clip
uscire dalla parte che è a sinistra della cascata a destra e a destra della cascata a sinistra.
Quindi le cadute verticali sono solo quad primitive di base, allungate alla lunghezza appropriata. Uso un altro shader per scorrere la trama della cascata sopra le cascate e la dissolvo alle estremità superiore e inferiore. Quindi strato su un sistema di particelle di schiuma nel punto di impatto per aiutare a coprire la miscela.
Ecco un primo piano in modo da poter vedere i componenti.
In cima ho una cascata "radice" per dare il via alle cose. Ogni fotogramma, dopo che tutti gli Update()
script sono stati eseguiti per spostare le cose in giro, spara CircleCast
verso il basso, per vedere se la sua acqua colpisce qualcosa. Se colpisce a WaterCatcher
, gli dice di mostrare la sua pelle a valle del punto ferita.
Determino "a valle" usando il colpo normale - se è molto vicino alla verticale, o se la cascata in arrivo attraversa i bordi che si inclinano in entrambe le direzioni, quindi versiamo sia a sinistra che a destra.
Ognuno WaterCatcher
ha una cascata a sinistra e una a destra, che abilita e posiziona sul suo lato più lontano se si rovescia in quella direzione - altrimenti rimangono nascosti. Queste cascate a loro volta CircleCast
scendono verso il basso per trovare ciò su cui si riversano, e così via ...
Il prototipo presenta ancora alcuni problemi visivi che potrebbero essere migliorati: il flusso d'acqua lungo un oggetto si apre contemporaneamente invece di animare, e le regole del flusso potrebbero usare un po 'più di tolleranza o isteresi in modo che non si interrompano facilmente oggetti rotanti. Penso che questi dovrebbero essere problemi abbastanza risolvibili.
Texture di sfondo, rocce e piattaforme rotanti via Kenney
Ecco i trucchi che uso nel mio shader di frammenti del collettore d'acqua:
// 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;