Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

If I wanted to fill my game screen with individually coloured pixels, how would I do this?

For example, if I wanted to write a 'game of life'-type game where each pixel was a cell, how would I achieve this using XNA?

I've tried just calling SetData() on a Texture2D object using a screen-sized array of Color values, but it complains with:

You may not call SetData on a resource while
it is actively set on the GraphicsDevice.
Unset it from the device before calling SetData.

How do I do as it asks? Or better still... is there an alternative, better, efficient way to fill a screen with arbitrary pixels?

share|improve this question
2  
Perhaps you are doing the SetData between SpriteBatch.Begin and SpriteBatch.End calls? –  r2d2rigo Dec 23 '10 at 14:08
    
@r2d2rigo: Answers should be answers, not comments, so I can really upvote that. –  user744 Dec 23 '10 at 15:24
    
Afraid not. The linked answer below leads to this - GraphicsDevice.Textures[0] = null; - which makes the texture inacvtive on the device, but why index 0 is a mystery. –  izb Dec 23 '10 at 15:28
    
@Joe: It was just a question, see izb's response telling that he wasn't doing it. It wasn't an answer per se, just asking for some info about how did he code it. –  r2d2rigo Dec 23 '10 at 17:53

3 Answers 3

It sounds like the texture is still selected into the GraphicsDevice (or at the very least in use still as the GPU is allowed to lag behind the CPU to achieve the best performance). I've not really used XNA so I can't really speak to the exact nature of that error.

However, if you do this with a single texture and managed to fix the above problem you would most likely incur a costly peformance bottleneck which requires the CPU to sit around waiting for the GPU to finish using that texture before it can lock it again (the CPU would be blocked from continuing until it could lock the texture knowing it was safe to do so). A better solution would be to create two textures and double-buffer their usage, so you write to Texture 1, then render with it, the next frame write to Texture 2 instead, render with it, switch back to Texture 1 again, etc. That way you can ensure the GPU won't be using the texture still and should also solve the problem you have now.

share|improve this answer
    
That's great, can you link to any examples of double-buffered textures used in this way? –  izb Jan 5 '11 at 14:27

For drawing lines and such I've just used a 1x1 white texture and scaled/rotated it. Not sure if that will be any faster, but it is an option

pixel = new Texture2D(graphicsDevice, 1, 1);
pixel.SetData<Color>(new Color[1] { Color.White });
share|improve this answer
    
Four vertices - or even one 2D vertex - is way more data than you would be sending by re-uploading a texture. –  user744 Dec 23 '10 at 22:49

If you're going to be plotting lots of pixels I recommend using a shader instead.. but I found this on stackoverflow: http://stackoverflow.com/questions/2569996/how-can-i-use-a-shader-in-xna-to-color-single-pixels

share|improve this answer
    
A shader is not really useful unless the state is specifiable using a stateless or smaller-state-to-transmit formula, which is not the case for the game of life. Otherwise, what you're feeding into the shader is a texture-sized buffer of data, which might as well just be the texture. –  user744 Dec 23 '10 at 15:23
    
A shader won't help, I agree. The linked answer does help though: GraphicsDevice.Textures[0] = null; will allow the texture to be modified. If the answer is edited, preferably explaining what index 0 is and why this works, I'll happily vote for that answer :) –  izb Dec 23 '10 at 15:30
1  
XNA 4.0 changed the way shaders work. When you use a shader, it is kept bound to the GPU until you set a new one (in 3.1 it was Effect.Begin and Effect.End, now it is Effect.Apply); and since SpriteBatch uses an internal shader that needs a texture (the sprite you want to draw), it is bound to the GraphicsDevice for quite some time after you use it. Setting GraphicsDevice.Texture[0] to null tells the GPU to stop using the first texture in the texture stage, which happens to be the one set by the SpriteBatch's shader. BTW, should I expand this in a separate answer? –  r2d2rigo Dec 23 '10 at 17:59
    
@r2d2rigo: Please do. (@izb: The index is zero because you're not multitexturing, so the only active texture unit is the first one.) –  user744 Dec 23 '10 at 22:45

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.