如何在XNA中逐个像素地绘制?

我正在尝试使用XNA逐个像素地在屏幕上绘图,但是我遇到了资源问题。 我认为最好的方法是使用1个纹理来更新每一帧,但是我无法更新它。 这是我到目前为止所做的,就像测试一样:

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(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); } 

当第二次调用Draw()时,我收到以下错误:

“操作已中止。您不能修改已在设备上设置的资源,也不能修改在平铺括号内使用的资源。”

如果我尝试在Draw()中创建一个新的Texture2D,我很快就会出现内存不足错误。 这适用于Windows Phone。 似乎我试图以错误的方式做到这一点,我还有什么其他选择才能让它发挥作用?

在调用SetData之前,请尝试设置GraphicsDevice.Textures[0] = null 。 根据您之后可能有更高效的方法的效果,您还可以考虑Silverlight WriteableBitmap。

编辑:这是我在模拟器中测试的代码:

 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(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); } 

你基本上需要在exception中提出要求:

要确保未在图形设备上设置纹理,请将其放在Draw的末尾:

 GraphicsDevice.Textures[0] = null; 

为确保您没有在平铺括号内Draw ,请不要在Draw中使用SetData 。 将调用SetData移动到Update


额外信息:您的内存不足错误是因为您没有释放Texture2D分配的非托管资源(垃圾收集器无法跟踪它们,因此它不知道您的内存不足)。 您需要在纹理上调用Dispose 。 然而,无论如何在每个帧中创建一个新的纹理是一个坏主意(没有办法避免它导致的性能和内存碎片问题)。