Il problema con l'uso di atlanti di trama e perdite di tex adiacenti ha a che fare con il modo in cui funziona il filtro di trama lineare.
Per qualsiasi punto della trama che non viene campionato esattamente al centro di un texel, il campionamento lineare campionerà 4 tex adiacenti e calcolerà il valore nella posizione richiesta come media ponderata (in base alla distanza dal punto di campionamento) di tutti i 4 campioni.
Ecco una bella visualizzazione del problema:
Poiché non è possibile utilizzare qualcosa di simile GL_CLAMP_TO_EDGE
a un atlante delle trame, è necessario creare dei texel di bordo attorno al bordo di ciascuna trama. Questi texel di bordo impediranno ai campioni vicini di trame completamente diverse nell'atlante di alterare l'immagine attraverso l'interpolazione ponderata spiegata sopra.
Si noti che quando si utilizza il filtro anisotropico, potrebbe essere necessario aumentare la larghezza del bordo. Questo perché il filtro anisotropico aumenterà la dimensione del vicinato del campione ad angoli estremi.
Per illustrare cosa intendo usando un bordo attorno al bordo di ogni trama, considera le varie modalità di avvolgimento disponibili in OpenGL. Prestare particolare attenzione a CLAMP TO EDGE
.
Nonostante ci sia una modalità chiamata "Clamp to Border", in realtà non è ciò che ci interessa. Quella modalità ti consente di definire un singolo colore da usare come bordo attorno alla tua texture per tutte le coordinate della texture che non rientrano nella norma [0.0 -1,0] intervallo.
Ciò che vogliamo è replicare il comportamento di CLAMP_TO_EDGE
, dove qualsiasi coordinata di trama al di fuori dell'intervallo corretto per la (sotto) trama riceve il valore dell'ultimo centro texel nella direzione in cui era fuori dai limiti. Dato che hai quasi il controllo completo su le coordinate della trama in un sistema di atlante, l'unico scenario in cui le coordinate della trama (efficaci) potrebbero riferirsi a una posizione al di fuori della trama sono durante la fase media ponderata del filtro della trama.
Sappiamo che GL_LINEAR
campioneremo i 4 vicini più vicini come mostrato nel diagramma sopra, quindi abbiamo solo bisogno di un bordo 1-texel. Potrebbe essere necessario un bordo texel più ampio se si utilizza il filtro anisotropico, poiché aumenta la dimensione del vicinato del campione in determinate condizioni.
Ecco un esempio di una trama che illustra più chiaramente il bordo, anche se per i tuoi scopi puoi allargare il bordo 1 texel o 2 texel.
(NOTA: il bordo a cui mi riferisco non è il nero attorno a tutti e quattro i bordi dell'immagine, ma l'area in cui la scacchiera smette di ripetersi regolarmente)
Nel caso ti stavi chiedendo, ecco perché continuo a far apparire il filtro anisotropico. Cambia la forma del vicinato del campione in base all'angolo e può causare l'uso di più di 4 texel per il filtraggio:
http://www.arcsynthesis.org/gltut/Texturing/ParallelogramDiag.svg
Maggiore è il grado di anisotropia che usi, più è probabile che dovrai affrontare quartieri campione contenenti più di 4 texel. Un bordo a 2 texel dovrebbe essere adeguato per la maggior parte delle situazioni di filtraggio anisotropico.
Ultimo ma non meno importante, ecco come sarebbe costruito un atlante di trama compresso che replicerebbe il GL_CLAMP_TO_EDGE
comportamento in presenza di un GL_LINEAR
filtro di trama:
( Sottrai 1 da X e Y nelle coordinate nere, non ho provato a leggere l'immagine prima di pubblicare. )
A causa dell'archiviazione dei bordi, la memorizzazione di 4 trame 256x256 in questo atlante richiede una trama con dimensioni 516x516. I bordi sono colorati in base al modo in cui li riempiresti di dati texel durante la creazione dell'atlante:
- Rosso = Sostituisci con texel direttamente sotto
- Giallo = Sostituisci con texel direttamente sopra
- Verde = Sostituisci con texel direttamente a sinistra
- Blu = Sostituisci con texel direttamente a destra
In questo esempio compresso, ciascuna trama nell'atlante utilizza una regione 258x258 dell'atlante, ma genererai coordinate di trama che mappano alla regione visibile 256x256. I texel confinanti vengono sempre usati solo quando il filtro delle trame viene eseguito ai bordi delle trame nell'atlante e il modo in cui sono progettati imita il GL_CLAMP_TO_EDGE
comportamento.
Nel caso ti stavi chiedendo, puoi implementare altri tipi di modalità di avvolgimento usando un approccio simile - GL_REPEAT
può essere implementato scambiando i texel del bordo sinistro / destro e superiore / inferiore nell'atlante delle trame e un po 'di matematica intelligente delle coordinate delle trame in un shader. È un po 'più complicato, quindi per ora non preoccuparti. Dato che hai a che fare solo con i fogli sprite, ti limiti a GL_CLAMP_TO_EDGE
:)
GL_NEAREST
oGL_LINEAR
per il rendering della trama?