notJustCode.it
 
\\ Home : Articoli
Stencil Buffer
Di RobyDx (del 25/03/2007 @ 14:57:55, in DirectX9, linkato 3030 volte)

Come abbiamo visto il backbuffer è una grossa superficie (diciamo una matrice grande quanto lo schermo) che contiene l'immagine che stiamo creando man mano che disegniamo cose; ogni volta che disegniamo qualcosa Direct3D non fa altro che cambiare il valore numerico dei pixel interessati dal disegno con quelli della nuova immagine. Il tutto quindi si riduce a numeri. Abbiamo anche visto che la seconda superficie è il depth buffer (detto anche Z buffer) responsabile delle profondità: quando viene disegnato un modello Direct3D controlla sullo Z buffer la profondità di ogni pixel e solo se la profondità è minore (il pixel del modello 3D si trova avanti a quelli precedentemente disegnati) fa modificare sia il backbuffer che il depth buffer. Lo stencil buffer è la terza superficie speciale di DirectX ed in qualche modo opzionale visto che si potrebbe benissimo vivere senza. Per spiegare il funzionamento farò un esempio.
Immaginate di renderizzare un cubo. Nelle zone interessate dal rendering vengono modificati i pixel del backbuffer ma possiamo tenere in memoria il fatto che in quei punti è stato disegnato un oggetto. In questo caso diciamo allo stencil buffer di memorizzare questo fatto. Ora abbiamo sulla superficie stencil dei valori che ci indicano dove è stato disegnato qualcosa oppure no. Abbiamo creato una maschera. Finchè non puliamo lo stencil possiamo dire a DirectX di non disegnare i quei punti o di disegnare solo lì.
Osservate la figura

 

Nella prima vignetta disegno degli oggetti e "sporco" lo stencil. Nella seconda non uso lo stencil e la figura copre completamente quelle sottostanti. Nella terza invece dico al device di non disegnare dove lo stencil ha valore diverso da zero. La figura rimane quindi forata in quei punti che vengono detti maschera. Lo stencil buffer serve a questo, a creare maschere.
Possiamo modificare i valori dello stencil in moltissimi modi ed ovviamente non esiste solo "bianco e nero", ma tantissimi valori che possiamo usare per creare molte maschere sullo schermo. Se ad esempio chiedo allo stencil buffer di aumentare i valori ogni volta di 1 accadrà che dove vengono tracciati più pixel il valore sarà più alto.
Le cose che si possono realizzare sono praticamente infinite e molti degli effetti che vedete (soprattutto per console) usano spesso lo stencil.

  • Visualizzare scene all'interno di figure irregolari (scena di quake 3 in cui si vedono i personaggi nella scritta "Quake III")
  • creare split screen irregolari
  • ombre super realistiche (prossimi tutorial)
  • filtri (si potrebbe inquadrare un scena con un visore a raggiX, lo stencil permetterebbe di visualizzare il retro dei muri salvati nello stencil)
  • riflessioni
    Questi sono solo un esiguo numero destinato a decuplicarsi quando si cominciano ad usare anche vertex e pixel shader (esempio il depth of field).
  • Codice

    Come per lo Z buffer lo stencil va creato in fase di inizializzazione.

    AutoDepthStencilFormat = DepthFormat.D24S8

    Ovviamente dopo il controllo della compatibilità.
    In questo caso (il più compatibile) viene creato uno Z buffer a 24bit ed uno stencil a 8 bit (totale 32 bit). Dal punto di vista matematico significa che lo stencil supporta 2^8 valori ossia 256 (da 0 a 255). Altri formati sono

    DepthFormat.D24X4S4
    DepthFormat.D15S1
    DepthFormat.D24SingleS8

    Queste sono scarsamente compatibili.
    Usate questa opzione nella creazione del device (sia fullscreen che in finestra). Ora avete anche lo stencil buffer ma non farà nulla finche non lo iniziate ad usare. Innanzitutto

    device.Clear(ClearFlags.Target Or ClearFlags.ZBuffer Or ClearFlags.Stencil, Color.Blue, 1, 0)

    Osservate le opzioni che puliscono anche lo stencil. Potete ovviamente non pulire lo stencil o pulire solo questo, a seconda di cosa vi serve. Per attivare lo stencil usate

    device.RenderState.StencilEnable = True

    mettetelo a false per disattivare l'effetto.

    device.RenderState.StencilFunction=Compare.Always
    device.RenderState.ReferenceStencil = 0

    Questa opzione (always a default) serve a stabilire come si devono comportare i pixel. Always significa che il pixel verrà disegnato sempre, indipendentemente dal valore dello stencil. Reference è il valore usato per il paragone. Altre opzioni

    Always =accetta sempre il nuovo pixel
    Never =non accetta mai il nuovo pixel
    GreaterEqual =solo dove il valore dello stencil del pixel è minore o uguale al reference
    NotEqual =solo dove lo stencil ed il reference hanno valore differente
    Greater = solo dove il valore dello stencil del pixel è minore al reference
    LessEqual =solo dove il valore dello stencil del pixel è maggiore o uguale al reference
    Equal =solo dove reference e stencil sono uguali
    Less =solo dove il valore dello stencil del pixel è maggiore al reference

    Tramite queste 2 opzioni i pixel dell'oggetto vengono (o non vengono) disegnati. Quando il pixel viene disegnato si dice che lo stencil test è passato altrimenti fallisce. Queste 2 possibilità (che possono verificarsi contemporaneamente per uno stesso oggetto) permettono di modificare i valori dello stencil

    device.RenderState.StencilPass = StencilOperation.Keep

    operazione eseguita quando il test passa

    device.RenderState.StencilFail = StencilOperation.Keep

    operazione quando il test fallisce
    In entrambi i casi le operazioni da scegliere sono

    Zero :in quel pixel lo stencil va a zero
    Replace :il valore viene sostituito con quello del reference
    Decrement :decrementa lo stencil del valore del reference. Se scende sotto zero il valore sale al massimo.
    Increment :incrementa lo stencil del valore del reference. Se sale sopra il massimo torna a zero.
    Invert :inverte il valore dello stencil (max - valore)
    DecrementSaturation :decrementa lo stencil del valore del reference. Non scende sotto lo zero
    IncrementSaturation :incrementa lo stencil del valore del reference. Non sale oltre al massimo.
    Keep :non modifica il valore

    Attenzione! Se un modello 3D è composto da più superfici visibili (ad esempio un cubo dietro un altro) effettua più operazioni, una per ogni pixel che viene rivolto verso lo schermo (anche se nascosto da altri pixel più avanti). Di conseguenza avrà più incrementi ma solo se la zona più in profondità viene renderizzata prima. Fate prove e vedrete.
    Altre funzioni

    device.RenderState.StencilZBufferFail

    Come pass e fail ma accade se lo stencil passa ma lo Z no (per oggetti dietro ad altri).

    StencilMask :maschera per lo stencil
    StencilWriteMask :maschera per il referenze

    Valore uguale a FFFFFFFF (valore esadecimale corrispondente a tanti uno: 1111 1111 1111 1111 1111 1111 1111 1111).
    Cosa significa? Serve per fare delle operazioni di maschera binaria (usata spesso per i codici IP e per altre cose). Funziona così:
    il numero 14 è in binario uguale a
    1110
    Con il numero 5 come maschera (che è uguale a 101) si effettua il prodotto carattere per carattere

  • 1110
  •   101
  • -------
  • 1100
  • Si usano per cambiare il valore dello stencil e del reference senza però modificarli definitivamente. Più che altro per poter trattare tutti insieme valori differenti. Ad esempio (valori fuori misura e in gruppi di 256)
    173.151 con maschera 256.0 significa che tutti i valori da 173.0 a 173.151 vengono considerati come 173.0. Con numeri più piccoli potete fare in modo che valori compresi ad esempio tra 4 e 16 siano considerati uguali a 4 e quindi usare la stessa proprietà per tutti senza dover andare ad eseguire lo stencil per tutte (se ad esempio vi serve come maschera solo i valori tra 4 e 8 mica potete mettere 4<8!).
    Cercate di afferrare il concetto e di applicarlo ai valori dello stencil (molti minori).

    Esempio di maschera

    In questo esempio vi dirò come creare una maschera semplice (un poligono in primo piano che non verrà disegnato ma che creerà una zona in cui disegnare).
    1) disegnate l'oggetto maschera con opzione always per stencil function pass uguale a replace e reference uguale ad un intero qualsiasi diverso da zero.
    2) fate il clear ma non dello stencil (solo backbuffer e Zbuffer)
    3)con stencil function equal, reference uguale a quel valore intero scelto all'inizio e function uguale a keep (per non modificare lo stencil) renderizzate la scena. L'oggetto verrà disegnato solo dove c'era la maschera.
    E se non voglio usare un clear? Allora sostituite la 1 con un never per stencil function e un replace nel Fail (l'oggetto non viene disegnato quindi fallisce il test dove dovrebbe essere disegnato). Non fate clear ed eseguite il 3: stesso risultato ma senza il clear e quindi più veloce.
    Altrimenti?
    Potete usare sempre il primo metodo ma modificare l'alphablending in modo da non disegnare nulla ma in realtà lo stencil lo considererà disegnato.
    Per utilizzare bene lo stencil ci vuole un pò di fantasia ed entrare nell'ottica delle somme e delle sottrazioni delle immagini. Vi lascio all'esempio che mostra la complessità dello stencil nei modelli (ossia quante volte incrementa lo stencil) e un esempio di maschera (il modello 3D fa da maschera). Fate pratica e vi impadronirete. Ultimo avvisi:
    attenti alla compatibilità ma anche alla pesantezza. Il depth è a 32 bit invece dei classici 16 e lo stencil attivato consuma risorse.

    Esempio VB.Net

    Esempio C#

    Articolo Articolo  Storico Storico Stampa Stampa
    I commenti sono disabilitati.
    "L'esperienza è quella cosa meravigliosa che permette di riconoscere un errore quando lo si commette di nuovo."

    F.P Jones


    Cerca per parola chiave
     

    Titolo
    Articoli (4)
    C++ (4)
    Direct3D10 (30)
    Direct3D11 (20)
    DirectX9 (82)
    DotNet (10)
    English (9)
    FanGames (22)
    ManagedDX11 (2)
    Materiale Utile (4)
    News (39)
    Shader Library (12)
    SharpDX (1)
    Software (25)
    Tecnologia (19)
    Varie (9)

    Gli interventi più cliccati

    Ultimi commenti:
    If you wish to retai...
    23/05/2013 @ 13:07:45
    Di chanel outlet
    You deficit of self-...
    23/05/2013 @ 13:07:13
    Di cartier watches uk
    Reinforce your own l...
    23/05/2013 @ 13:06:37
    Di replica watches
    Whenever you"re shiv...
    23/05/2013 @ 13:06:11
    Di swiss replica watches
    It's likely you have...
    23/05/2013 @ 13:05:02
    Di chanel handbags
    Cheap automobile ins...
    23/05/2013 @ 13:04:28
    Di replica watches

    Titolo
    Con quale tecnologia state realizzando o avete intenzione di realizzare i vostri progetti?

     DirectX11
     DirectX10
     DirectX9
     XNA
     DirectX8 o Precedenti
     OpenGL
     Motori grafici già pronti
     Altro

    Titolo
    Umorismo (17)

    Le fotografie più cliccate



    Ci sono 134 persone collegate
    Sono state visualizzate  pagine

    17/06/2024 @ 06:44:46
    script eseguito in 42 ms