2010-09-18 7 views
14

Questa è solo una breve domanda prima di approfondire la conversione del mio attuale sistema di rendering in openGL. Ho sentito che le trame dovevano essere in 2 dimensioni di base per essere conservate per il rendering. È vero?Can OpenGL ES può riprodurre trame di dimensioni non base 2?

La mia applicazione è molto stretta in memoria, ma la maggior parte delle bitmap non sono potenze di due. La memorizzazione di trame non base 2 consuma più memoria?

+1

potenza di due! = Quadrato. 32x64 è potenza di due, non quadrata, 13x13 è quadrata, non potenza di due. – Bahbar

+0

Buon punto. Tuttavia, in entrambi i casi deve essere non potere di due. – GuyNoir

risposta

10

È vero in base alla versione OpenGL ES, OpenGL ES 1.0/1.1 ha il potere di due restrizioni. OpenGL ES 2.0 non ha la limitazione, ma limita le modalità di avvolgimento per la mancata alimentazione di due trame.

Creazione di trame più grandi per abbinare le dimensioni del POT fa sprecare memoria texture.

+0

Quindi non c'è assolutamente modo di rendere una potenza di una bitmap di due dimensioni con openGL senza sprecare memoria? Questo è fastidioso. Oh bene, felice di non aver ancora iniziato a revisionare il mio codice. – GuyNoir

+0

Con OpenGL ES 1.0/1.1, n. –

+0

A proposito, dovresti sapere che OpenGL ES e OpenGL non hanno gli stessi limiti, OpenGL 2.0 e oltre supporta direttamente le trame NPOT. –

3

No, deve essere una base 2. Tuttavia, puoi aggirare questo aggiungendo barre nere nella parte superiore e/o inferiore dell'immagine, quindi utilizzando l'array di coordinate della trama per limitare il punto in cui la trama verrà mappata dall'immagine. Ad esempio, diciamo che hai una trama di 13 x 16 pixel. È possibile aggiungere 3 pixel di nero sul lato destro poi effettuare le seguenti operazioni:

static const GLfloat texCoords[] = { 
     0.0, 0.0, 
     0.0, 13.0/16.0, 
     1.0, 0.0, 
     1.0, 13.0/16.0 
    }; 

Ora, si ha un file di immagine 2base, ma una texture non 2base. Assicurati di utilizzare il ridimensionamento lineare :)

+0

Il problema qui è che spreca memoria texture; qualcosa di cui sono molto pressato con la mia applicazione. – GuyNoir

6

Suresh, la potenza della limitazione di 2 è stata incorporata in OpenGL negli (molto) primi giorni della grafica computerizzata (prima dell'accelerazione hardware accessibile), ed è stata eseguita per motivi di prestazioni. Il codice di rendering di basso livello ottiene un notevole incremento delle prestazioni quando può essere hardcoded per le texture power-of-two. Anche nelle moderne GPU, le trame POT sono più veloci delle trame NPOT, ma la differenza di velocità è molto più piccola di un tempo (sebbene possa essere ancora visibile su molti dispositivi ES).

GuyNoir, quello che dovresti fare è costruire un atlante di texture. Ho appena risolto questo problema io stesso lo scorso fine settimana per il mio gioco Android. Ho creato una classe chiamata TextureAtlas e il suo costruttore chiama glTexImage2D() per creare una trama grande di qualsiasi dimensione che scelgo (passando null per i valori dei pixel). Quindi posso chiamare add (id, bitmap), che chiama glTexSubImage2D(), ripetutamente per impacchettare le immagini più piccole. La classe TextureAtlas tiene traccia dello spazio utilizzato e libero all'interno della trama più grande e i rettangoli in cui è memorizzata ogni bitmap. Quindi il codice di rendering può chiamare get (id) per ottenere il rettangolo per un'immagine all'interno dell'atlante (che può quindi convertire in texture coordinate).

Nota a margine n. 1: Scegliere il modo migliore per imballare in varie dimensioni di trama NON è un compito banale. Ho scelto di iniziare con la logica semplice nella classe TextureAtlas (pensa macchina da scrivere + ritorno a capo + avanzamento riga) e assicurati di caricare le immagini nel miglior modo possibile per sfruttare questa logica. Nel mio caso, era quello di iniziare con le più piccole immagini quadrate e lavorare fino alle immagini quadrate medie. Quindi carico qualsiasi immagine corta + larga, forza un CR + LF e poi carica qualsiasi immagine alta + magra. Per ultimo, carico le immagini quadrate più grandi.

Nota a margine n. 2: Se sono necessari più atlanti di trama, provare a raggruppare le immagini all'interno di ciascuna che verrà renderizzata insieme per ridurre al minimo il numero di volte che è necessario cambiare le trame (che può uccidere le prestazioni). Ad esempio, nel mio gioco Android ho inserito tutti gli elementi statici della scheda di gioco in un unico atlante e tutti i fotogrammi di vari effetti di animazione in un secondo atlante. In questo modo posso associare l'atlante n. 1 e disegnare tutto sul tabellone, quindi posso associare l'atlante n. 2 e disegnare tutti gli effetti speciali su di esso. Due texture selezionate per frame sono molto efficienti.

Nota a margine n. 3: Se è necessario ripetere/eseguire il mirroring delle trame, è necessario inserire le proprie trame e ridimensionarle (non aggiungere pixel neri per riempire i bordi).

+0

Sì, ho considerato qualcosa di simile. L'unica cosa è che ci sono ancora alcune piccole quantità di memoria sprecata, e in un programma in cui spingo costantemente i limiti di 24mb, ho bisogno di tutta la memoria che posso ottenere. – GuyNoir

1

Questo è un po 'in ritardo, ma non potenza di 2 texture sono supportato in OpenGL ES 1/2 attraverso le estensioni.

Il principale è GL_OES_texture_npot. C'è anche GL_IMG_texture_npot e GL_APPLE_texture_2D_limited_npot per i dispositivi iOS

Controlla queste estensioni chiamando glGetString(GL_EXTENSIONS) e cercando l'estensione che ti serve.

Vorrei anche consigliare di mantenere le tue trame in taglie che sono multipli di 4 come un po 'di hardware allunga le trame se non lo sono.