» it.Tutorial Morphing della Geometria basato sulla GPU 1
This site relies heavily on Javascript. You should enable it if you want the full experience. Learn more.

it.Tutorial Morphing della Geometria basato sulla GPU 1

English | French | Russian | Japanese

Precedente: L'approccio basato sulla CPU

GPU. L'approccio semplice

Preparare gli oggetti per il morphing

Con questo approccio faremo affidamento su di un effetto/shader. Giocheremo con i dati della geometria (i vertici) delle meshes e scriveremo un semplice vertexshader. Ogniqualvolta si inizi a scrivere un effetto in vvvv è bene cominciare con un nodo Template (EX9.Effect). In questo esempio useremo due cilindri, a meno che tu non voglia usare delle meshes che hai preparato all'uopo. Orsù, prepara una patch simile a questa:

Tieni presente che il nodo Camera (Transform Softimage) ed il nodo AspectRatio (Transform) non sono essenziali, ma se ti stai chiedendo perché non siano essenziali, allora dovresti generarli, connetterli e farci pratica.

Infilare due meshes in una

Quindi siamo qui perché abbiamo scoperto che l'altro approccio non è il massimo, e che, invece, passare per la GPU ci permetterebbe di caricare di poligoni la scheda grafica come fosse un mulo, e soprattutto perché ci piace un casino scrivere codice. Allora come facciamo a connettere le due (o più) meshes all'effetto? Il punto è che non è possibile avere più di una mesh connessa ad un effetto, ma è possibile aggirare il problema costruendo una mesh che contenga i dati geometrici di entrambi (tutti) gli oggetti per il morphing.

La patch qui sopra mostra come stipare le componenti della posizione e delle normali di due meshes in una. Fai attenzione in particolare al nodo VertexBuffer (EX9.Geometry Join). Aprendolo in un Ispettore si potrà sbloccare alcuni alcuni pins addizionali: se un vertexbuffer può contenere una sola componente chiamata "posizione, position" ed una sola componente chiamata "normale, normal", può però contenere fino ad 8 componenti chiamate "coordinate della texture, texture coordinate". Queste sono quindi a disposizione per il nostro intento. Tramite l'Ispettore generiamo altri due pins sul nodo VertexBuffer (EX9.Geometry Join) selezionando "3D TexCoords" come valore per i primi due pins "Enable Texture Coordinate ..". Ora possiamo anche immettere posizioni e normali del secondo oggetto per il morphing nel vertexbuffer.

Il fatto che inseriamo dati della posizione/normali nelle componenti del vertexbuffer chiamate "3D TexCoords" non ha importanza. Più tardi, quando cominceremo a scrivere il vertexshader dovremo ricordarci di questa cosa ed impostare tutto perché questi dati in arrivo dal vertexbuffer vengano letti correttamente. La semantica ci verrà in aiuto.

Il pin "Apply" dei nodi VertexBuffer (EX9.Geometry Join) e Mesh (EX9.Geometry Join) ha bisogno solo di un BANG per far sì che le meshes cambino (nel nostro esempio per cambiare il raggio di uno dei cilindri). Finché questi nodi non applicano nuovi valori, nessuna risorsa viene utilizzata!

Il vertexshader

Il resto della magia succederà all'interno del vertexshader. Apri il nodo Template (EX9.Effect) con un clic del tasto destro e clicca, nel pannello a sinistra, su TFixedFunction. Dato che non ci sarà alcuna funzione fissa nell'effetto morphing possiamo cancellare questa tecnica (oppure tutte le righe sotto: technique TFixedFunction...) e salvare la template (Ctrl+Shift+S) con un nostro nome tipo PrimoMorph.fx
Prima di tutto abbiamo bisogno di un pin Fattore di Morph, MorphFactor, sull'effetto e di due pins colore. Li generiamo aggiungendo queste righe:

float MorphFactor;
float4 Color1: COLOR;
float4 Color2: COLOR;

proprio sotto le righe (in cima al codice dell'effetto):

//transforms
float4x4 tW: WORLD;        //la matrice mondo dei modelli
float4x4 tV: VIEW;         //matrice vista, come impostata tramite il Renderer (EX9)
float4x4 tP: PROJECTION;
float4x4 tWVP: WORLDVIEWPROJECTION;
 
float MorphFactor;
float4 Color1: COLOR;
float4 Color2: COLOR;

Nota come l'effetto conti già tre pins in più dopo aver aggiunto queste righe (a patto che tu salvi l'effetto, stavolta con Ctrl+S, dato che non corriamo più il rischio di sovrascrivere la template nativa di vvvv).
Ora individua le righe

vs2ps VS(
   float4 PosO  : POSITION,
   float4 TexCd : TEXCOORD0)
{
...

nell'effetto. Connotano la funzione vertexshader.
Questa riga:

Out.Pos = mul(PosO, tWVP);

è quella che ci interessa. Qui dice che i dati in ingresso della posizione del primo cilindro (PosO) verranno trasformati per la matrice mondovistaproiezione, worldviewprojection matrix, (tWVP) ed emessi come il risultato dell'effetto (Out.Pos). Qui è dove ci intrufoleremo e mescoleremo la posizione in ingresso del primo cilindro con quella del secondo.

Ma come facciamo a sapere che la variabile in ingresso PosO indica i dati posizione del primo cilindro? Perché la variabile è segnata con la semantica POSITION. Così, se vogliamo accedere alla posizione del secondo oggetto del morphing che abbiamo inserito nel vertexbuffer col nome di "TexCoord0", possiamo farlo dichiarando una variabile ed assegnandogli la semantica TEXCOORD0. Che ci è già stata preparata.

float4 TexCd : TEXCOORD0;

Dato che non abbiamo bisogno delle coordinate della texture nel nostro esempio possiamo rinominare la variabile in "PosO2".

float4 PosO2: TEXCOORD0;

ora abbiamo l'accesso ad entrambi gli oggetti del morphing e lo possiamo effettuare. Un modo con una logica un po' complicata (ma "leggibile") è quello di rimpiazzare la riga:

Out.Pos = mul(PosO, tWVP);

con:

Out.Pos = mul(MorphFactor * PosO + (1-MorphFactor) * PosO2, tWVP);

o fare uso della funzione intrinseca di hlsl "lerp", che compie la stessa azione:

Out.Pos = mul(lerp(PosO, PosO2, MorphFactor), tWVP);

Ora dovrebbe segnalare un errore che riporta a proposito della variabile "TexCd" che abbiamo sostituito con "PosO2"; basterà cancellare la riga:

Out.TexCd = mul(TexCd, tTex);

Ora l'effetto si dovrebbe compilare e cambiando il valore del pin "MorphFactor" nella patch il morphing dovrebbe già rispondere.

Dobbiamo ancora fare il morphing per i colori. Ma questo è facile, basta trovare la funzione pixelshader:

float4 PS(vs2ps In): COLOR
{
   float4 col = tex2D(Samp, In.TexCd);
   return col;
}

e sostituirla con:

float4 PS(vs2ps In): COLOR
{
   return lerp(Color1, Color2, MorphFactor);
}

Ecco fatto.

Bonus

Ora non vorrai vedere queste mesh con un colore che non dà alcun senso di profondità. Allora prendi un nodo GouraudDirectional (EX9.Effect), salvalo con un altro nome (è importante! se non lo si salva con un altro nome e lo si modifica, si modificherà il nodo nativo di vvvv!) ed applica le stesse modifiche che abbiamo portato al nodo Template (EX9.Effect). Ora, oltre che ai dati sulla posizione, dovrai applicare il morphing anche alle normali!

Precedente: L'approccio basato sulla CPU

anonymous user login

Shoutbox

~2d ago

joreg: The summer season of vvvv workshops at The NODE Institute is out: https://thenodeinstitute.org/ss24-vvvv-intermediates/

~2d ago

domj: If you happen to be in Prague, come join us at the Schema workshop on Thursday 25.4. :) https://www.facebook.com/events/395516526614988/?ti=ls

~14d ago

joreg: Postponed: Next vvvv beginner course starting April 29: https://thenodeinstitute.org/courses/vvvv-beginner-class-summer-2024/

~1mth ago

~1mth ago

joreg: The Winter Season of vvvv workshops is now over but all recordings are still available for purchase: https://thenodeinstitute.org/ws23-vvvv-intermediates/