2009-12-18 14 views
5

Sto analizzando il mio semplice gioco 2D XNA. Ho scoperto che il 4% dell'intero tempo di esecuzione è preso da un semplice operando di sommare due colori, uno dei quali moltiplicato per float.Ottimizza la manipolazione del colore su XNA

Ho bisogno di chiamare questo metodo rogulthy 2000 volte per frame (per ogni tile sulla mappa), che mi ha dato 120000 volte al secondo per i 60 fps di XNA. Anche l'aumento minimo della singola chiamata potrebbe dare un enorme impatto sulla velocità. Eppure semplice non so come posso fare questo più efficace

private void DoColorCalcs(float factor, Color color) 
    { 
     int mul = (int)Math.Max(Math.Min(factor * 255.0, 255.0), 0.0); 
     tile.Color = new Color(
      (byte)Math.Min(tile.Color.R + (color.R * mul/255), 255), 
      (byte)Math.Min(tile.Color.G + (color.G * mul/255), 255), 
      (byte)Math.Min(tile.Color.B + (color.B * mul/255), 255)); 

    } 

EDIT: Come suggerito da Michael Stum:

private void DoColorCalcs(float factor, Color color) 
    { 
     factor= (float)Math.Max(factor, 0.0); 
     tile.Color = new Color(
      (byte)Math.Min(tile.Color.R + (color.R * factor), 255), 
      (byte)Math.Min(tile.Color.G + (color.G * factor), 255), 
      (byte)Math.Min(tile.Color.B + (color.B * factor), 255)); 
    } 

Questa abbassata e getta dal 4% al 2,5%

+2

La parola che stai cercando è ottimizzare, non ottimizzare. :) – jalf

+0

Sembra un sacco di chiamate per un semplice gioco 2D. Non puoi invece cambiare l'algoritmo generale? Ad esempio memorizzando i risultati o evitando di fare tutto ogni frame? – Jan

+0

Ho bisogno di ricalcolare le luci dinamiche per le tessere (il mio modello di illuminazione include lo sfarfallio della luce, che cambia l'intensità della luce al tasso Sin (tempo) * 0,1 per una tessera data in ogni fotogramma) – PiotrK

risposta

1

La mia prima domanda è, perché virgola mobile? Se stai semplicemente ridimensionando i colori per attenuarli, non hai bisogno di molta precisione. Esempio:

int factorTimes256; 
tile.Color.R = Math.Max(255, tile.Color.R + (color.R * factorTimes256)/256); 
// same for G and B 

In altre parole, rappresentano vostro fattore come un intero da 0 a 256, e fare tutti i calcoli su interi. Non hai bisogno di più precisione di 8 bit perché il risultato è solo 8 bit.

La mia seconda domanda è, hai detto che sei passato dal 4% al 2,5% in questo codice? Questo è piccolo. Le persone che usano profiler che fanno solo strumentazione o campionano il contatore del programma sono spesso soddisfatti di piccoli miglioramenti. Scommetto che ci sono altre cose che richiedono molto più tempo, che potresti attaccare. Here's an example of what I mean.

1

Il ovvio miglioramento sarebbe quello di includere l'operazione di divisione (/ 255) nel calcolo di mul, per ridurre le divisioni da 3 a una singola divisione:

private void DoColorCalcs(float factor, Color color) 
{ 
    float mul = Math.Max(Math.Min(factor * 255.0f, 255.0f), 0.0f)/255f; 
    tile.Color = new Color(
     (byte)Math.Min(tile.Color.R + (color.R * mul), 255), 
     (byte)Math.Min(tile.Color.G + (color.G * mul), 255), 
     (byte)Math.Min(tile.Color.B + (color.B * mul), 255)); 
} 

Detto questo, dal momento che si sta sostituendo tile.Color, può in realtà essere più veloce di sostituirlo al posto invece di sovrascriverlo (anche se mi piacerebbe il profilo di questo per vedere se aiuta):

private void DoColorCalcs(float factor, Color color) 
{ 
    float mul = Math.Max(Math.Min(factor * 255.0f, 255.0f), 0.0f)/255f; 
    tile.Color.R = (byte)Math.Min(tile.Color.R + (color.R * mul), 255); 
    tile.Color.G = (byte)Math.Min(tile.Color.G + (color.G * mul), 255); 
    tile.Color.B = (byte)Math.Min(tile.Color.B + (color.B * mul), 255); 
} 

Ciò impedisce il ricalcolo del canale alfa e può ridurre un po 'la quantità di istruzioni.

+0

(int) Math.Max ​​(Math.Min (fattore * 255.0, 255.0) , 0.0)/255 risulteranno in 0 nella maggior parte dei casi. Quindi questo non aiuta. –

+0

D'accordo con Simon Ottenhaus - stai dividendo l'intero 0..255 per 255 che ti ha dato 254 zeri e il valore singolo "uno" – PiotrK

+0

Ah, ho dimenticato - Ho provato a sostituire la creazione di nuovo oggetto Color impostando le sue variabili. Richiedeva un po 'di "approccio cattivo" in quanto dovevo cambiare tile.Color da Accessor type a Variable. Ma ancora non ha avuto alcun impatto sulla velocità (test e risultato arrotondato a 0,1 fps) – PiotrK