XNA 4.0 Replacing Pixel Color

Started by
3 comments, last by phil_t 11 years, 2 months ago

Hi there,

I was hoping to simply get some direction.I want independent images to have an effect applied to them, where a y value parameter (which will increase/decrease) determines where the effect should be applied to the image. For example:

- Let's say the example image has a height of 100 pixels

- We'll start the y value at 0

Because the y value is at 0 the effect should be applied along the first row of pixels in the image (row 0). The game will update the y value, thus moving the effect up/down the image (like a scan animation, I suppose).

Now.. the effect I'm looking to do seems simple. I just want to replace a single color, a range of colors,or all the colors of the row, specified by y, with another single color. I can figure this part out.

The main problem for me, is figuring out how to apply and updating value, like y, to the effect on a single image... among many images. If anyone could point me in a good direction, I'd be grateful. It's also probably worth mentioning that i'm using XNA 4.0, and this game is using 2D spritebatch. Thanks for reading.

Nokame

Advertisement
Hmm... Since you mentioned XNA in tag...

Texture editing is quite simple to perform:
void EditTexture(Texture2D Texture)
{
// You need to initialize one 1D and one 2D array first
Color[] TextureArray = new Color[Texture.Width * Texture.Height];
Color[,] TextureField = new Color[Texture.Width, Texture.Height];

// This will give you the color of your texture for each pixel; GetData retuns a 1D array
Texture.GetData(TextureArray);

// For easier manipulation, transform your 1D into 2D array
for (int x = 0; x < Texture.Width; x++)
     for (int y = 0; y < Texture.Height; y++)
           TextureField[x, y] = TextureArray[x + y * tileTexture.Height];

// Using double For loop to go through the pixels, perform whatever editing you need

// After editing, you need to put everything back into 1D array
for (int x = 0; x < Texture.Width; x++)
     for (int y = 0; y < Texture.Height; y++)
           TextureArray[x + y * Texture.Height] = TextureField[x, y];

// We'll make a new object so that edit of the texture doesn't affect all instances of that texture
Texture = new Texture2D(Texture.GraphicsDevice, Texture.Width, Texture.Height);

// Save an edited texture
Texture.SetData(TextureArray);
}
I hope this is self explanatory enough smile.png
Short explanation: you extract the color data via Texture.GetData method into a 1D array, transform 1D array into 2D for easier manipulation, perform whatever manipulation you have to (like swapping Color.Red for Color.Green), transform it back into 1D array and save as new texture.

Of course, you need to write your own modification to satisfy your needs.

Be careful, Texture.SetData affects ALL instances of an object (so if you "scan" a paper on one location, all papers will be "scanned").

Also, you mentioned adding effects to your sprite... I rather wouldn't tinker with the sprites to do that but draw effects on top of the sprites, either with same or new SpriteBatch. Reason is that image manipulation like this is time consuming and you'll also need to track where and when you need to draw original image, image with effect etc.

I hope this helps.

I apologize for not being clear.

The effect would be applied to a rendertarget2d surface, not the image itself. So in the above "example" the y = 0 parameter would cause the surface's pixel-row 0 to be altered, not the image pixel-row 0. Aurioch's method is something I want to avoid beacuse it seems like it has needless overhead to do it during runtime, whereas applying color effects using HLSL seems to be very easy... I just want to apply that color effect to a single row of pixels (given an updating value: y) on the surface, rather than the entire surfafce.

Thanks.

Well, this is what i'm talking about. I'll use the following in my draw method

effect.Parameters["y"].SetValue(0); // At y = 0 the rendertarget2d surface top row is altered using hlsl.

Not sure why it took me so long to find. I haven't tried to implement yet, but I'm sure it'll work fine... I've also been toying around with another way to get the desired effect. Thanks for the feedback.

Yes, you can do it that way.

You could also just draw the appropriate portion of the sprite a second time with the desired effect. That way your shaders are a little simpler. But... whatever is easiest.

This topic is closed to new replies.

Advertisement