2011-01-29 10 views
6

Sto provando a disegnare sullo schermo pixel per pixel usando XNA, ma sto avendo problemi con le risorse. Ho pensato che il modo migliore sarebbe avere 1 texture che aggiorni ogni fotogramma, ma ho difficoltà ad aggiornarlo. Ecco quello che ho finora, proprio come un test:Come disegnare 2D pixel per pixel in XNA?

Texture2D canvas; 
Rectangle tracedSize; 
UInt32[] pixels; 

protected override void Initialize() 
    { 
     tracedSize = GraphicsDevice.PresentationParameters.Bounds; 
     canvas = new Texture2D(GraphicsDevice, tracedSize.Width, tracedSize.Height, false, SurfaceFormat.Color); 
     pixels = new UInt32[tracedSize.Width * tracedSize.Height];    

     base.Initialize(); 
    } 

protected override void Draw(GameTime gameTime) 
    { 
     GraphicsDevice.Clear(Color.CornflowerBlue); 

     pixels[100] = 0xFF00FF00; 
     canvas.SetData<UInt32>(pixels, 0, tracedSize.Width * tracedSize.Height); 

     spriteBatch.Begin(); 
     spriteBatch.Draw(canvas, new Rectangle(0, 0, tracedSize.Width, tracedSize.Height), Color.White); 
     spriteBatch.End(); 

     base.Draw(gameTime); 
    } 

Quando Draw() viene chiamato per la seconda volta, ottengo il seguente errore:.

"L'operazione è stata interrotta L'utente non può modificare una risorsa che è stata impostata su un dispositivo o dopo che è stata utilizzata all'interno di una staffa di piastrellatura. "

Se provo a creare una nuova Texture2D in Draw(), ottengo rapidamente un errore di memoria insufficiente. Questo è per Windows Phone. Sembra che sto provando a farlo nel modo sbagliato, quali altre opzioni devo fare per farlo funzionare?

+0

Non conoscevo la risposta, quindi ho cercato su google "struttura procedurale xna" (che è ciò che viene chiamato questo genere di cose). Non sembra essere un modo semplice e integrato per farlo. Ci sono almeno tre suggerimenti comuni (buffering, comandi texture GPU, farlo in uno shader). L'ultimo è ovviamente ottimale, ma richiede conoscenze di programmazione shader. Potresti voler eseguire la stessa ricerca e sfogliare ciò che è là fuori. – Tergiver

risposta

5

Provare a impostare GraphicsDevice.Textures[0] = null prima di chiamare SetData. A seconda dell'effetto che stai cercando potrebbe esserci un metodo più performante, potresti anche considerare Silverlights WriteableBitmap.

Edit: Questo è il codice che ho provato nell'emulatore:

Texture2D canvas; 
Rectangle tracedSize; 
UInt32[] pixels; 

protected override void Initialize() 
{ 
    tracedSize = GraphicsDevice.PresentationParameters.Bounds; 
    canvas = new Texture2D(GraphicsDevice, tracedSize.Width, tracedSize.Height, false, SurfaceFormat.Color); 
    pixels = new UInt32[tracedSize.Width * tracedSize.Height]; 

    base.Initialize(); 
} 
Random rnd = new Random(); 
protected override void Draw(GameTime gameTime) 
{ 
    GraphicsDevice.Clear(Color.CornflowerBlue); 

    GraphicsDevice.Textures[0] = null; 
    pixels[rnd.Next(pixels.Length)] = 0xFF00FF00; 
    canvas.SetData<UInt32>(pixels, 0, tracedSize.Width * tracedSize.Height); 

    spriteBatch.Begin(); 
    spriteBatch.Draw(canvas, new Rectangle(0, 0, tracedSize.Width, tracedSize.Height), Color.White); 
    spriteBatch.End(); 

    base.Draw(gameTime); 
} 
+0

GraphicsDevice.Textures [0] = null non funziona. – Curyous

+0

Grazie mille, l'ho fatto funzionare dal tuo esempio. Penso che la prima volta che l'ho provato avrei potuto creare un Texture2D in Draw(). – Curyous

3

È fondamentalmente bisogno di fare come si chiede nella eccezione:

Per garantire che la trama non è impostata sulla grafica dispositivo, mettere questo alla fine del Draw:

GraphicsDevice.Textures[0] = null; 

per garantire che non sta disegnando all'interno di una staffa di piastrelle, non utilizzare SetData all'interno di Draw a tutti. Spostare la chiamata a SetData in Update. Informazioni


Bonus: Il tuo errore di out-of-memoria è perché non state liberando le risorse non gestite che Texture2D alloca (il garbage collector non può tenerne traccia, in modo che non sa si sta esaurendo di memoria). Hai bisogno di chiamare Dispose sulla trama. Tuttavia, creare una nuova trama ogni fotogramma è una cattiva idea (non c'è modo di evitare i problemi di prestazioni e frammentazione della memoria che provoca).