Trame di fogli sprite che raccolgono i bordi della trama adiacente


10

Ho una routine di sprite personalizzata (openGL 2.0) che utilizza un semplice foglio di sprite (le mie trame sono disposte orizzontalmente una accanto all'altra).

Quindi, ad esempio, ecco un foglio sprite di prova con 2 semplici trame:

inserisci qui la descrizione dell'immagine

Ora, ciò che faccio quando creo il mio oggetto sprite openGL è specificare il numero totale di fotogrammi nel suo atlante e, durante il disegno, specificare quale fotogramma voglio disegnare.

Quindi determina da dove afferrare la trama:

Divisione del numero di fotogrammi richiesto per il numero totale di fotogrammi (per ottenere la coordinata sinistra)

E quindi immergere 1 per il numero totale di fotogrammi e aggiungere il risultato alla coordinata della mano sinistra calcolata sopra.

Questo sembra funzionare, ma a volte ho problemi. Ad esempio, voglio disegnare la X in basso e ottengo ...........

inserisci qui la descrizione dell'immagine

Ho sentito parlare di un 'imbottitura' di 1 px tra ogni trama, ma qualcuno potrebbe spiegare esattamente come funziona? Voglio dire, se lo faccio, eliminerà sicuramente i calcoli per ottenere la trama.

Se includo semplicemente l'imbottitura nella trama raccolta (quindi lo sprite è disegnato con un bordo bianco), sicuramente questo causerà problemi con il rilevamento delle collisioni? (vale a dire che gli sprite possono apparire in collisione quando si utilizzano i box di delimitazione quando le parti trasparenti si scontrano).

Gradirei se qualcuno potesse spiegare.


Stai utilizzando GL_NEARESTo GL_LINEARper il rendering della trama?
MichaelHouse

Sto usando GL_Linear @ Byte56
BungleBonce il

Risposte:


15

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_EDGEa 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.

  http://lucera-project.com/blog/wp-content/uploads/2010/06/wrap.png

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_LINEARcampioneremo 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_EDGEcomportamento in presenza di un GL_LINEARfiltro 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_EDGEcomportamento.

Nel caso ti stavi chiedendo, puoi implementare altri tipi di modalità di avvolgimento usando un approccio simile - GL_REPEATpuò 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:)


Grazie @AndonMColeman, potresti mostrare il bordo in un diagramma in quanto non sono ancora sicuro di capire come funziona - di nuovo significherà che quando la trama viene applicata al mio oggetto includerà il bordo? Voglio che la trama reale vada fino ai bordi del mio quad - scusate se non lo capisco correttamente - apprezzerei qualche dettaglio in più - grazie
BungleBonce

@ user22241 Certamente, il modo in cui funziona questo bordo è duplicando il texel sul bordo della trama.
Andon M. Coleman,

@ user22241: No, questo bordo non sarà visibile in circostanze normali. Tratterai le tue texture impaccate come se avessero le stesse dimensioni per il calcolo delle coordinate della trama, applicherai solo un offset per saltare il bordo. L'intero punto del bordo è impedire al campionamento lineare delle trame di raggiungere e campionare texel che appartengono a immagini separate nel foglio sprite. Se si utilizza il campionamento del vicino più vicino, nulla di tutto ciò è necessario, ma si ottengono cattivi sprite con alias.
Andon M. Coleman,

Risposta brillantemente dettagliata - grazie! Solo un'ultima cosa se potessi. Come definirei l'offset da aggiungere alle coordinate della mia trama? Ho ragione nel dire che sarebbe semplicemente 1 / widthOfTexture?
BungleBonce,

@ user22241: Sì, l'inizio dell'immagine della trama sarebbe + 1 / widthOfTexture nella direzione X e + 1 / heightOfTexture nella direzione Y. Avrai un bordo attorno a ogni trama. Quando si desidera calcolare le coordinate della trama per la terza trama orizzontale, la posizione compressa per questa trama è in realtà +5 texels (+2 texels per il bordo della prima texture, +2 per il bordo della seconda texture e +1 per l'inizio di questa trama) oltre alla larghezza delle altre 2 trame. Sembra complicato solo scriverlo; Posso tracciarti un diagramma se necessario :)
Andon M. Coleman,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.