English | Spanish | Mandarin | Japanese
INDICE: it.Of Effects and Shaders
Precedente: Pixelshader, i preparativi
Prossimo: Le Coordinate della Texture
float4 PS(vs2ps In): COLOR
{
return 1;
}
Questa funzione viene richiamata per ogni pixel occupato da una mesh sullo schermo.
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 è:
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.
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?
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.
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;
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
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.
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.
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);
anonymous user login
~2d ago
~9d ago
~9d ago
~10d ago
~23d ago
~1mth ago
~1mth ago
~1mth ago
~1mth ago
~2mth ago