La versione di Pixel shader 1.4 si differenzia completamente dalle precedenti non solo per il maggior numero di registri texture e temporary a disposizione ma soprattutto per l’introduzione di un meccanismo articolato in 2 fasi, uno in cui elaborare le texture fin dal posizionamento delle coordinate e l’altro in cui fondere i risultati. Questo tuttavia modifica notevolmente la situazione facendo perdere di significato molte istruzioni e cambiando addirittura significato ai registri. Passiamo subito alle piccole differenze.
Il numero di massimo di istruzioni da utilizzare era 8 per la versione 1.0 e 1.1 e 12 per le versioni 1.2 e 1.3. Nella versione 1.4 si possono usare invece fino a 14 istruzioni per fase e quindi un totale di 28 istruzioni. I temporary registri passano da 2 a 6 e i texture register da 4 a 6. I texture register tuttavia cambiano completamente connotazione. Infatti nelle versioni precedenti queste venivano usate per caricare i colori o le coordinate texture in quel pixel. Qui invece i registri “Tn” contengono le coordinate texture n-esime provenienti direttamente dalla mesh (o dal vertex shader). Tuttavia non possono essere usati in funzioni aritmetiche ma solo in operazioni di caricamento di dati dalla texture.
Istruzione phase
L’istruzione phase serve per separare le due fasi.
Ps.1.4
:;struzioni
………
phase
;istruzioni
……….
Nella versione pixel shader 1.4 è possibile caricare le texture cambiando le coordinate per ogni singolo pixel. Tramite il processo di doppia fase possiamo caricare una stessa texture 2 volte, ognuna con coordinate texture differenti in modo da poterle ad esempio interpolare. L’istruzione phase quindi rilascia le risorse texture permettendo di ricaricarle ma lasciando inalterati gli altri registri. L’unica cosa che perderete è la componente alpha dei registri Rn costringendovi quindi a calcolare eventuali trasparenze dopo. Alcune istruzioni e registri funzionano diversamente nelle 2 fasi. Ad esempio i registri V non si possono usare nella prima fase.
Registri
I registri validi in ps 1.4 sono gli stessi:
Vn: sono 2, il primo, V0, corrispondente al colore diffuse che arriva dal vertex shader, il secondo, V1, corrispondente al colore specular. Sono solo in lettura. Si possono usare solo nella seconda fase. Rn: sono i registri temporanei da usare come variabili. Sono 8 ed il primo, R0, è il colore finale che il pixel shader deve assolutamente restituire e quindi va riempito assolutamente con dei valori. Tn: sono 6 e contengono le coordinate texture provenienti dagli shader. Sono solo in lettura e non si possono usare in tutte le istruzioni ma solo in quelle per le texture. Cn: provengono direttamente dal device a cui vengono passati direttamente dal codice Visual Basic. Sono solo in lettura.
I registri sono composti da 4 elementi (r,g,b,a) corrispondenti ai 4 colori. Nella versione 1.4 potete leggere o scrivere su quelli che volete semplicemente scrivendo un punto e i colori che volete dopo qualsiasi registro. Es r0.r, c0.gb
Istruzioni
Le istruzioni sono diminuite nella versione 1.4 perchè sostituite dalla possibilità di spostare le coordinate texture.
Add dest, src0, src1
Esegue la somma tra registri.
Es add r0,r1,v0 esegue la somma tra r1 e v0 e la inserisce in r0
Bem dest.rg, src0,src1
Esiste solo nella versione 1.4 e può essere usata solo nella prima fase e solo una volta. Applica il bump mapping secondo la regola
dest.r = src0.r + D3DTSS_BUMPENVMAT00(stage n) * src1.r
+ D3DTSS_BUMPENVMAT10(stage n) * src1.g
dest.g = src0.g + D3DTSS_BUMPENVMAT01(stage n) * src1.r
+ D3DTSS_BUMPENVMAT11(stage n) * src1.g
Il registro su cui si scrive deve necessariamente avere gli elementi rg selezionati (es r0.rg).
Cmp dest, src0, src1, src2
Se src0 è maggiore di 0 inserisce nel dest src1 altrimenti src2 (confronto fatto valore per valore).
Cnd dest, src0, src1, src2
Come sopra ma valutà su 0.5 invece che su 0.
Def dest, fVal0, fVal1, fVal2, fVal3
Crea un registro C (es def C0, 0.0f, 1.0f, 0.5f, 0.0f) senza doverlo caricare dal device.
Dp3 dest, src0, src1 (Dp4 dest, src0, src1)
Effettua un dot product su 3 (4) valori tra i registri src0 e src 1.
Lrp dest, src0, src1, src2
Effettua una interpolazione lineare tra il registro src1 e src2 in base al valore di src0.
Mad dest, src0, src1, src2
Moltiplica il src0 per il src1 e aggiunge il src2
Mov dest, src
Copia il src nel dest
Mul dest, src0, src1
Esegue il prodotto tra registri.
Es mul r0,r1,v0 esegue il prodotto tra r1 e v0 e la inserisce in r0
Nop
Non fa nulla, per sprecare un ciclo.
Phase
Separa le 2 fasi
Ps.1.4
Prima istruzione da scrivere, dichiara che il codice pixel shader è usato nella versione 1.4
Sub dest, src0, src1
Esegue la differenza tra registri
Es sub r0,r1,v0 esegue la differenza tra r1 e v0 e la inserisce in r0
Texcrd dest, src
Copia le coordinate texture specificate dal src (che deve essere un registro T) nella destinazione. Si deve usare prima delle operazioni aritmetiche nelle 2 fasi. Copia solo le coordinate uvw quindi il registro di destinazione avrà l’elemento alpha non inizializzato (quindi dovete scriverci sopra o non usarlo).
Es texcrd r1,t3 copia le coordinate del terzo slot della texture nel registro r1.
Texdepth r5
Usa i valore r5.r / r5.g per il depth test (quindi per lo Z buffer). Si può usare solo il registro r5 e una volta usato il registro è bruciato, ossia non potete più usarlo in altre istruzioni.
Texkill src
Se uno degli elementi è minore di zero il pixel non viene disegnato. Potete usare anche i registri Tn.
Texld Dn, src
Copia il colore del pixel della texture numero n nel registro di destinazione usando la coordinata texture scritta nel src. Quindi il registro su cui scrivete corrisponde necessariamente alla texture n-esima che leggete. Come sorgente potete usare o un registro T o nella seconda phase un registro Rn. Non potete copiare una texture più di una volta per fase.
Es texld r1,t0 copia il pixel della texture numero 1 con le coordinate della texture numero 0.
Texld r3,r2 copia il pixel della texture numero 3 con le coordinate scritte in r2
Le istruzioni sono finite, poche ma buone.
Modificatori
Potete usare dei suffissi accanto alla istruzione per moltiplicare, dividere o saturare (ossia rendere i valori compresi tra 0 e 1) i registri di destinazione.
_x2, _x4, _x8 moltiplica per 2,4,8
_d2, _d4, _d8 divide per 2,4,8
_sat satura
es
add_x4 r0,r1,v0 farà in modo che il registro r0 sarà moltiplicato per 4.
Modificatori di registri
Potete fare delle operazioni sui registri direttamente nelle istruzioni aggiungendo dei suffisso ai registri o facendo una operazione.
registro_bias : sottrae 0.5 al registro. Es add r0,v0,r1_bias
1-registro : inverte il registro. Es add r0,v0,1-r0
- registro : cambia segno al registro. Es add r0,v0,-r1
registro_x2 : moltiplica per 2 il registro. Es add r0,v0,r1_x2
registro_bx2: moltiplica per 2 dopo aver sottratto 0.5. Es add r0,v0,r1_bx2
Struttura del codice
Il codice và scritto nel seguente ordine
1. ps.1.4 2. istruzioni def per definire costanti 3. fino a sei operazioni di indirizzamento texture 4. fino a 8 operazioni aritmetiche 5. phase 6. fino a 6 operazioni di indirizzamento texture 7. fino a 8 operazioni aritmetiche Il valore che si troverà in r0 sarà il colore finale del pixel. Potete anche non usare il metodo delle 2 fasi se non vi serve. In questo caso
8. ps.1.4 9. istruzioni def per definire costanti 10. fino a 6 operazioni di indirizzamento texture 11. fino a 8 operazioni aritmetiche Data la comodità di poter cambiare le coordinate del pixel da prendere tramite il secondo registro i pixel shader 1.4 sono comodi per calcoli che richiedono di dover prendere pixel in posizioni diverse da quello da calcolare. Potete quindi prendere i pixel che circondano quello che state elaborando per l'elaborazione dei cosiddetti filtri (esempio filtro di Gauss per il blur o quello di Sobel per l'outlining). Attenzione alla compatibilità della vostra scheda con la versione pixel shader.