Domanda

Ho letto da qualche parte che durante il rendering di molti oggetti 3D si potrebbero unire questi per formare una maglia gigante in modo da effettuare una sola chiamata di disegno. Pertanto, lasciando che la, quote: "GPU faccia la sua magia", mentre la CPU è gratuita per altre chiamate oltre al disegno.

Quindi, alla mia domanda, sarebbe possibile farlo in un ambiente 2D con rendimento in mente?

Ad esempio, supponiamo di avere un semplice sistema di tessere e invece di effettuare una chiamata per ogni tessera in vista, si dovrebbe invece unire tutte le tessere per formare uno sprite di grandi dimensioni e quindi chiamare un disegno su di esso.

Qualsiasi approfondimento sull'argomento - suggerimenti, collegamenti o quant'altro - è molto apprezzato poiché non ho alcuna esperienza precedente nelle prestazioni grafiche.

Modifica: Ci scusiamo per la mia scarsa spiegazione. Sto creando un tileengine per uso personale e voglio che sia il più versatile possibile. Pertanto, voglio ottimizzare nel caso in cui dovessi disegnare molte tessere nel prossimo futuro.

Uso un foglio di piastrelle, ma ciò che intendevo con la domanda è se l'unione di tutte le tessere che devono essere disegnate dal foglio in una nuova Texture2D otterrà prestazioni. Ad esempio:

Abbiamo 128x72 tessere da disegnare sullo schermo. Invece di scorrere tutte le tessere e chiamare il disegno per ogni tessera da disegnare, uniamo tutte le tessere in una nuova sprite di dimensioni 1280x720 e la disegniamo. In questo modo il metodo draw () verrà chiamato una sola volta per frame . La mia domanda era se ciò migliorasse le prestazioni in quanto avrebbe unito gli oggetti 3d in una singola mesh durante il 3D.

Perché le informazioni che ho raccolto sono che chiamare draw () è un maiale delle prestazioni e dovrebbe essere chiamato il meno possibile. Qualcuno da confermare o negare? :)

È stato utile?

Soluzione

Non ho alcuna esperienza con XNA e 3D, ma ti darò alcuni consigli per i giochi 2D. Ho trascorso un po 'di tempo a creare un motore per piastrelle in XNA all'inizio di quest'anno e mi chiedevo la stessa cosa. Penso che la risposta breve qui sia sì, combinare le tue tessere in uno sprite più grande è una buona idea se sei preoccupato per le prestazioni. Tuttavia, c'è una risposta molto più lunga se sei interessato.

In generale, quando si tratta di ottimizzazioni delle prestazioni, la risposta è quasi sempre, "non farlo." Se sei sicuro di dover ottimizzare le prestazioni, la risposta successiva è quasi sempre, "non farlo ancora." Infine, se si tenta di ottimizzare le prestazioni, la cosa più importante che si può fare è utilizzare i benchmark per raccogliere misurazioni precise delle prestazioni prima e dopo le modifiche. Senza quello, non sai se ci riesci!

Ora, più legato ai giochi 2D, ho imparato che ho visto prestazioni molto migliori nel mio motore di tessere meno ho cambiato trama. Ad esempio, supponiamo che io abbia una tessera erba e una tessera ghiaia. Se queste sono due trame separate in memoria, e disegno una tessera erba, quindi una tessera ghiaia, quindi una tessera erba sullo schermo, la GPU caricherà la trama dell'erba, quindi la spegnerà per caricare la trama ghiaia, quindi cambi trama di erba di nuovo dentro per disegnare un'altra tessera erba. Questo uccide le prestazioni molto rapidamente! Il modo più semplice per aggirare questo problema è quello di avere un foglio di sprites, in cui metti le tessere erba e ghiaia in una trama e dì semplicemente a SpriteBatch di disegnare ogni volta da un'area diversa sulla stessa trama.

Un'altra cosa da considerare è quante tessere disegnerai sullo schermo contemporaneamente. Non riesco a ricordare in modo specifico, ma stavo disegnando migliaia di piastrelle contemporaneamente (in una vista ingrandita). Ho notato che quando ho usato tessere più grandi e ne ho disegnate meno, come suggerisci nella tua domanda, anche le prestazioni sono migliorate. Questo non è stato un grande miglioramento come quello che ho descritto nell'ultimo paragrafo, e ti incoraggio comunque a misurare i cambiamenti delle prestazioni derivanti da diverse implementazioni. Inoltre, se stai disegnando solo una dozzina o poche centinaia di tessere, potrebbe non valerne la pena provare a ottimizzarlo in questo momento (vedi il secondo paragrafo).

Solo per sapere che non lo sto inventando del tutto, ecco un link a un post di Shawn Hargreaves su texture swap, fogli di calcolo, ecc. Probabilmente ci sono post migliori sui forum XNA e sul blog di Shawn Hargreaves se cerchi sull'argomento.

http://forums.xna.com/forums/p/ 24254 / 131437.aspx # 131.437

Aggiornamento:

Da quando hai aggiornato la tua domanda, fammi aggiornare il mio post. Ho deciso di confrontare alcuni campioni per darti un'idea di quali potrebbero essere le differenze di prestazioni. Nella mia funzione Draw () ho il seguente:

        GraphicsDevice.Clear(Color.CornflowerBlue);

        Stopwatch sw = new Stopwatch();
        sw.Start();

        spriteBatch.Begin();

#if !DEBUG
        spriteBatch.Draw(tex, new Rectangle(0, 0, 
                         GraphicsDevice.Viewport.Width,
                         GraphicsDevice.Viewport.Height), 
                         Color.White);            
#else
        for (int i = 0; i < 128; i++)
            for (int j = 0; j < 72; j++)
            {
                Rectangle r = new Rectangle(i * 10, j * 10, 10, 10);
                spriteBatch.Draw(tex, r, r, Color.White);
            }
#endif
        spriteBatch.End();

        sw.Stop();

        if (draws > 60)
        {
            numTicks += sw.ElapsedTicks;
        }
        draws++;

        if (draws % 100 == 0)
            Console.WriteLine("avg ticks: " + numTicks / (draws - 60));

        base.Draw(gameTime);

Rilascia il punto esclamativo in " #if! DEBUG " istruzione per passare tra i due metodi. Ho saltato i primi 60 sorteggi perché includevano alcune impostazioni iniziali (non sono sicuro di cosa) e stavano distorcendo le medie. Ho scaricato un'immagine 1280x720 e per il test case superiore l'ho disegnata una volta. Per il caso di test in basso ho disegnato l'immagine sorgente in riquadri, 128x72 come hai chiesto nella tua domanda. Ecco i risultati.

Disegnare un'immagine:

avg ticks: 68566
avg ticks: 73668
avg ticks: 82659
avg ticks: 81654
avg ticks: 81104
avg ticks: 84664
avg ticks: 86626
avg ticks: 88211
avg ticks: 87677
avg ticks: 86694
avg ticks: 86713
avg ticks: 88116
avg ticks: 89380
avg ticks: 92158

Disegno di tessere 128x72:

avg ticks: 7902592
avg ticks: 8052819
avg ticks: 8012696
avg ticks: 8008819
avg ticks: 7985545
avg ticks: 8028217
avg ticks: 8046837
avg ticks: 8291755
avg ticks: 8309384
avg ticks: 8336120
avg ticks: 8320260
avg ticks: 8322150
avg ticks: 8381845
avg ticks: 8364629

Come puoi vedere, c'è un paio d'ordine di differenza di magnitudo lì, quindi è abbastanza significativo. È abbastanza semplice testare questo tipo di cose e ti consiglio di eseguire i tuoi benchmark per la tua configurazione specifica per tenere conto di qualcosa che potrei aver perso.

Altri suggerimenti

Meno la scheda grafica deve cambiare trama, migliori sono le prestazioni. Puoi ordinare in base a Texture nel metodo SpriteBatch.Begin () se lo desideri, in modo che la scheda grafica cambi le trame il meno possibile.

Metto le mie piastrelle / folletti nei fogli quando ha senso. Ad esempio, un personaggio può trovarsi in un foglio e uno strato di tessere può trovarsi nello stesso foglio. Finora ha funzionato abbastanza bene.

Direi che non ottimizzare fino a quando non è necessario. Se i tuoi giochi funzionano abbastanza velocemente, è per questo motivo che ti preoccupi dell'ottimizzazione.

  

Rectangle r = new Rectangle (i * 10, j * 10, 10, 10);

La creazione di molti nuovi oggetti chiamerà la garbage collection che può rallentare molto! non dovresti allocare nuovi oggetti in grandi loop:

La prestazione non è un imperativo universale o un comandamento di Dio; è un mezzo per raggiungere un fine. Se ciò che hai eseguito abbastanza bene, non hai letteralmente nulla da guadagnare dal miglioramento delle sue prestazioni. Mantenimento di "le migliori prestazioni possibili in ogni momento" è la definizione di ottimizzazione prematura e causerà più mal di testa di quanto prevenga.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top