» it.Tutorial Effects - Gestire il colore
This site relies heavily on Javascript. You should enable it if you want the full experience. Learn more.

it.Tutorial Effects - Gestire il colore

English | Spanish | Mandarin | Japanese

INDICE: it.Of Effects and Shaders
Precedente: Pixelshader, i preparativi
Prossimo: Le Coordinate della Texture


Il codice sul quale dobbiamo concentrarci adesso è la funzione pixelshader:

  1. float4 PS(vs2ps In): COLOR
  2. {
  3.     return 1;
  4. }

Questa funzione viene richiamata per ogni pixel occupato da una mesh sullo schermo.

float4 = il colore di un pixel

Come vedi la funzione ha come tipo di ritorno un float4. PS è il nome della funzione, e potrebbe essere in realtà qualunque cosa, a meno che non corrisponda ad un elemento specificato nel blocco della tecnica, technique block alla fine del codice.

Il float4 che la funzione deve restituire è un vettore con i 4 componenti che formano il colore di un pixel. L'ordine di questi componenti è:

  • rosso
  • verde
  • blu
  • alpha

Così, se invece di restituire, "return", 1, facessimo restituire un float4 come questo

return float4(1, 0, 0, 1);

il rettangolo, quad, sarebbe completamente rosso, dato che l'intervallo per ogni componente è compreso tra 0 e 1 (non tra 0 e 255).

Invece che restituire il float4 direttamente come sopra, si può prima definire una variabile di tipo float4, farci qualcosa, e quindi restituire la variabile:

float4 col;
col = float4(1, 0, 0, 1);
col /= 2;     //sintassi breve per col = col / 2
return col;

Il risultato sarà un rosso scuro, dato che la variabile col dopo la divisione per 2, contiene questi valori:

 (0.5, 0, 0, 0.5)

Nota come le operazioni matematiche sul tipo float4 (come la divisione operata prima) vengano eseguite su tutti i componenti del vettore allo stesso tempo.

Accedere a singoli componenti/canali di un colore

Si possono effettuare delle operazioni sui singoli canali di colore, così, ad esempio:

float4 col = float4(1, 0, 0, 1);
col.g = col.r / 2;
return col;

che restituirà in output:

 (1, 0.5, 0, 1)

L'uso dei cosiddetti swizzles (quindi swizzling) consente di accedere ai singoli componenti di un vettore. Gli swizzles di base per i quattro canali del colore sono .r, .g, .b e .a, e possono essere arrangiati in qualsiasi ordine, così:

 col = col.bgra;

Ne consegue che l'output precedente verrebbe riordinato in questo modo:

 (0, 0.5, 1, 1)

Sono consentite tutte le combinazioni usando lo swizzling, anche cose di questo tipo:
.rrgg
.rb
.abba
...chiaro il concetto?

Mostrare una texture

Attraverso il pin Filename sul nodo FileTexture (EX9.Texture) scegli un'immagine qualsiasi.

Per accedere ad una texture in un pixelshader e restituire il colore di uno dei suoi pixel è necessaria una riga di codice:

return tex2D(Samp, In.TexCd);

Qui viene restituito direttamente il risultato della funzione tex2D (di tipo float4) come colore dei pixels. La funzione prende un campionatore, sampler, come primo parametro ed una coordinata della texture come secondo input.

Facendo doppio clic su una parola, nell'editor vengono evidenziate tutte le parole uguali: se lo si fa con la variabile Samp del sampler si può notare come sia definita in alto nel codice. Un sampler è una struttura che combina una texture ed alcuni stati del sampler stesso. Per ora non approfondiremo oltre la questione e lasceremo da parte anche le coordinate della texture.

Ora proviamo a fare qualcosa con i canali dei colori della texture:

float4 col = tex2D(Samp, In.TexCd);
return col.bgra;

Prima campioniamo il colore di un'immagine assegnandogli una variabile col, poi, invece che far restituire il colore così com'è, invertiamo i canali rosso e blu e facciamo restituire questo risultato.

float4 col = tex2D(Samp, In.TexCd);
return col.b;  //sintassi breve per: return float4(col.b, col.b, col.b, col.b)

Oppure scegliamo di applicare il canale blu dell'immagine a tutti e quattro i canali.

Invertire i colori di una texture

Per invertire i colori di una texture, e lasciare il canale alpha così com'è, si procede così:

float4 col = tex2D(Samp, In.TexCd);
col.rgb = 1 - col.rgb;
return col;

Modificare il Contrasto di una texture

Il contrasto di un'immagine può essere amplificato aumentando tutti i valori del colore sopra 0.5, o attenuato diminuendo tutti i valori del colore sotto 0.5. Il prossimo passo consiste nel sottrarre 0.5 ai valori rgb, per portarli ad un valore prossimo allo zero; quindi, inseriamo una semplice moltiplicazione per il fattore di contrasto, così che, modificando il contrasto, potremo spostare il valore dei canali sopra e sotto lo zero; infine andiamo a riportare l'intervallo di valori dei canali tra 0 e 1. In sostanza

  • prima si abbassano i valori per consentire al contrasto di sfruttare la porzione più ampia possibile dell'intervallo 0...1 impedendogli inoltre di uscire da questo intervallo,
  • poi c'è l'intervento del contrasto
  • quindi, tornando a sommare 0.5, si fa si che l'azione del contrasto sia graduale (provate a togliere la riga aggiungendo al suo inizio //, come se fosse un commento)
float4 col = tex2D(Samp, In.TexCd);
col.rgb -= 0.5;
col.rgb *= Contrast;
col.rgb += 0.5;
return col;

Se si salva a questo punto si otterrà un errore:

 undeclared identifier 'Contrast'

dato che Contrast non è ancora stato definito. Basta aggiungere proprio sopra la funzione pixelshader

 float Contrast = 1;

per definire una variabile di nome Contrast ed inizializzarla con il valore 1. Dopo aver salvato, notare come in automatico sia stato generato un pin col nome Contrast nel nodo Effetto -cambiando il valore di questo pin si cambierà il contrasto dell'immagine.

Conversione in scala di grigi

Così come si può trovare su internet, c'è una semplice formula per convertire un colore nel valore corrispondente di scala di grigi, tenendo conto della luminosità percepita di ognuno dei tre canali. L'idea è quella di sommare insieme il 30% del canale rosso, il 59% di quello verde, e l'11% del blu.
Può essere fatto così:

float4 col = tex2D(Samp, In.TexCd);
col.rgb = col.r * 0.3 + col.g * 0.59 + col.b * 0.11;
return col;

o più elegantemente usando il dot product tra due vettori:

const float3 lumCoeff = {0.3, 0.59, 0.11};
col.rgb = dot(col.rgb, lumCoeff);

che permette di ottenere lo stesso risultato.

Riutilizzare il codice nelle funzioni

Se volessimo usare la funzione per convertire in scala di grigi più di una volta nel codice, invece di riscrivere il codice, è possibile definire una funzione che contenga questo codice e riutilizzarla quando si vuole. Genera quindi una funzione col nome ConvertToGray che restituisce un float4 ed accetta un float4 come input:

float4 ConvertToGray(float4 col)
{
    const float4 lumcoeff = {0.3, 0.59, 0.11, 0};
    return dot(col, lumcoeff);
}

Potrà essere usata nella funzione principale pixelshader in questo modo:

float4 col = tex2D(Samp, In.TexCd);
return ConvertToGray(col);

Prossimo: Le Coordinate della Texture
Precedente: Pixelshader, i preparativi
INDICE: it.Of Effects and Shaders

anonymous user login

Shoutbox

~2d ago

joreg: vvvvTv S02E01 is out: Buttons & Sliders with Dear ImGui: https://www.youtube.com/live/PuuTilbqd9w

~9d ago

joreg: vvvvTv S02E00 is out: Sensors & Servos with Arduino: https://visualprogramming.net/blog/2024/vvvvtv-is-back-with-season-2/

~10d ago

fleg: hey there! What's the best tool for remote work? Teamviewer feels terrible. Thanks!

~23d ago

joreg: Last call: 6-session vvvv beginner course starting November 4: https://thenodeinstitute.org/courses/ws24-5-vvvv-beginners-part-i/

~1mth ago

joreg: Missed the last meetup? You can rewatch it here: https://www.youtube.com/live/MdvTa58uxB0?si=Fwi-9hHoCmo794Ag

~1mth ago

theurbankind: When is the next big event, like node festival ?

~1mth ago

~1mth ago

joreg: Join us for the next vvvv meetup on Oktober 17th: https://visualprogramming.net/blog/2024/25.-vvvv-worldwide-meetup/

~2mth ago

joreg: 6 session beginner course part 2 "Deep Dive" starts January 13th: https://thenodeinstitute.org/courses/ws24-5-vvvv-beginners-part-ii/