2011-01-29 9 views
6

Estoy tratando de dibujar en la pantalla píxel por píxel usando XNA, pero tengo problemas con los recursos. Pensé que la mejor manera sería tener 1 textura que actualice cada fotograma, pero tengo problemas para actualizarla. Esto es lo que tengo hasta ahora, al igual que una prueba:Cómo dibujar 2D píxel por píxel en 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); 
    } 

Cuando Draw() se llama la segunda vez, me sale el siguiente error:.

"La operación fue abortada Usted no puede modifique un recurso que se haya configurado en un dispositivo, o después de que se haya utilizado dentro de un paréntesis de mosaico ".

Si trato de crear una nueva Texture2D en Draw(), obtengo rápidamente un error de falta de memoria. Esto es para Windows Phone. Parece que estoy tratando de hacerlo de la manera incorrecta, ¿qué otras opciones tengo para que funcione?

+0

No sabía la respuesta, así que busqué en Google "xna textura de procedimiento" (que es lo que se llama este tipo de cosas). No parece haber una forma simple e integrada de hacerlo. Hay al menos tres sugerencias comunes (almacenamiento en búfer, comandos de textura de GPU, hacerlo en un sombreador). El último es obviamente óptimo, pero requiere conocimiento de programación de sombreadores. Es posible que desee realizar la misma búsqueda y examinar lo que hay por ahí. – Tergiver

Respuesta

5

Pruebe la configuración GraphicsDevice.Textures[0] = null antes de llamar a SetData. Dependiendo del efecto que persiga puede haber un método más eficaz, también podría considerar Silverlights WriteableBitmap.

Editar: Este es el código que he probado en el emulador:

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 no funciona. – Curyous

+0

Muchas gracias, lo hice funcionar a partir de su ejemplo. Creo que la primera vez que lo intenté pude haber estado actualizando un Texture2D en Draw(). – Curyous

3

Es, básicamente, tiene que hacer lo que le pide en la excepción:

Para asegurarse de que la textura no se encuentra en los gráficos dispositivo, poner esto al final de Draw:

GraphicsDevice.Textures[0] = null; 

para asegurar que no se está dibujando el interior de un soporte de suelo de baldosas, no utilice el interior SetData de Draw en absoluto. Mueva la llamada al SetData al Update. información


Bonus: Su error de falta de memoria es porque no se están liberando los recursos no administrados que Texture2D asigna (el recolector de basura no pueden realizar un seguimiento de ellos, por lo que no sabe que está acabando de memoria). Debe llamar al Dispose en la textura. Sin embargo, crear una nueva textura de cada fotograma es una mala idea de todos modos (no hay forma de evitar el rendimiento y los problemas de fragmentación de memoria que causa).

Cuestiones relacionadas