Monogame Shader Porting Issues - c#

Ok so I ported a game I have been working on over to Monogame, however I'm having a shader issue now that it's ported. It's an odd bug, since it works on my old XNA project and it also works the first time I use it in the new monogame project, but not after that unless I restart the game.
The shader is a very simple shader that looks at a greyscale image and, based on the grey, picks a color from the lookup texture. Basically I'm using this to randomize a sprite image for an enemy every time a new enemy is placed on the screen. It works for the first time an enemy is spawned, but doesn't work after that, just giving a completely transparent texture (not a null texture).
Also, I'm only targeting Windows Desktop for now, but I am planning to target Mac and Linux at some point.
Here is the shader code itself.
sampler input : register(s0);
Texture2D colorTable;
float seed; //calculate in program, pass to shader (between 0 and 1)
sampler colorTableSampler =
sampler_state
{
Texture = <colorTable>;
};
float4 PixelShaderFunction(float2 c: TEXCOORD0) : COLOR0
{
//get current pixel of the texture (greyscale)
float4 color = tex2D(input, c);
//set the values to compare to.
float hair = 139/255; float hairless = 140/255;
float shirt = 181/255; float shirtless = 182/255;
//var to hold new color
float4 swap;
//pixel coordinate for lookup
float2 i;
i.y = 1;
//compare and swap
if (color.r >= hair && color.r <= hairless)
{
i.x = ((0.5 + seed + 96)/128);
swap = tex2D(colorTableSampler,i);
}
if (color.r >= shirt && color.r <= shirtless)
{
i.x = ((0.5 + seed + 64)/128);
swap = tex2D(colorTableSampler,i);
}
if (color.r == 1)
{
i.x = ((0.5 + seed + 32)/128);
swap = tex2D(colorTableSampler,i);
}
if (color.r == 0)
{
i.x = ((0.5 + seed)/128);
swap = tex2D(colorTableSampler, i);
}
return swap;
}
technique ColorSwap
{
pass Pass1
{
// TODO: set renderstates here.
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
And here is the function that creates the texture. I should also note that the texture generation works fine without the shader, I just get the greyscale base image.
public static Texture2D createEnemyTexture(GraphicsDevice gd, SpriteBatch sb)
{
//get a random number to pass into the shader.
Random r = new Random();
float seed = (float)r.Next(0, 32);
//create the texture to copy color data into
Texture2D enemyTex = new Texture2D(gd, CHARACTER_SIDE, CHARACTER_SIDE);
//create a render target to draw a character to.
RenderTarget2D rendTarget = new RenderTarget2D(gd, CHARACTER_SIDE, CHARACTER_SIDE,
false, gd.PresentationParameters.BackBufferFormat, DepthFormat.None);
gd.SetRenderTarget(rendTarget);
//set background of new render target to transparent.
//gd.Clear(Microsoft.Xna.Framework.Color.Black);
//start drawing to the new render target
sb.Begin(SpriteSortMode.Immediate, BlendState.Opaque,
SamplerState.PointClamp, DepthStencilState.None, RasterizerState.CullNone);
//send the random value to the shader.
Graphics.GlobalGfx.colorSwapEffect.Parameters["seed"].SetValue(seed);
//send the palette texture to the shader.
Graphics.GlobalGfx.colorSwapEffect.Parameters["colorTable"].SetValue(Graphics.GlobalGfx.palette);
//apply the effect
Graphics.GlobalGfx.colorSwapEffect.CurrentTechnique.Passes[0].Apply();
//draw the texture (now with color!)
sb.Draw(enemyBase, new Microsoft.Xna.Framework.Vector2(0, 0), Microsoft.Xna.Framework.Color.White);
//end drawing
sb.End();
//reset rendertarget
gd.SetRenderTarget(null);
//copy the drawn and colored enemy to a non-volitile texture (instead of render target)
//create the color array the size of the texture.
Color[] cs = new Color[CHARACTER_SIDE * CHARACTER_SIDE];
//get all color data from the render target
rendTarget.GetData<Color>(cs);
//move the color data into the texture.
enemyTex.SetData<Color>(cs);
//return the finished texture.
return enemyTex;
}
And just in case, the code for loading in the shader:
BinaryReader Reader = new BinaryReader(File.Open(#"Content\\shaders\\test.mgfx", FileMode.Open));
colorSwapEffect = new Effect(gd, Reader.ReadBytes((int)Reader.BaseStream.Length));
If anyone has ideas to fix this, I'd really appreciate it, and just let me know if you need other info about the problem.

I am not sure why you have "at" (#) sign in front of the string, when you escaped backslash - unless you want to have \\ in your string, but it looks strange in the file path.
You have wrote in your code:
BinaryReader Reader = new BinaryReader(File.Open(#"Content\\shaders\\test.mgfx", FileMode.Open));
Unless you want \\ inside your string do
BinaryReader Reader = new BinaryReader(File.Open(#"Content\shaders\test.mgfx", FileMode.Open));
or
BinaryReader Reader = new BinaryReader(File.Open("Content\\shaders\\test.mgfx", FileMode.Open));
but do not use both.

I don't see anything super obvious just reading through it, but really this could be tricky for someone to figure out just looking at your code.
I'd recommend doing a graphics profile (via visual studio) and capturing the frame which renders correctly then the frame rendering incorrectly and comparing the state of the two.
Eg, is the input texture what you expect it to be, are pixels being output but culled, is the output correct on the render target (in which case the problem could be Get/SetData), etc.

Change ps_2_0 to ps_4_0_level_9_3.
Monogame cannot use shaders built on HLSL 2.
Also the built in sprite batch shader uses ps_4_0_level_9_3 and vs_4_0_level_9_3, you will get issues if you try to replace the pixel portion of a shader with a different level shader.
This is the only issue I can see with your code.

Related

How to apply barrel distortion (lens correction) with SharpDX?

i've made a small application to grap screenshots from any windowed game and send it to the iPhone to creat an virtual reality app, like oculus rift (see https://github.com/gagagu/VR-Streamer-Windows-Server for more info).
The images will be captured with SharpDX and everything is working fine.
Now i want to implement such like lens correction (barrel distortion) and i'm looking for the fastest way to realize it. I'm looking many internet sites with informations about barrel distortion and i think the fastest way is to use a shader for it, but i'm very new to sharpdx (and no knowledge about shaders) and i don't know how to implement a shader to my code. The most tutorials applys a shader to an object (like a cube) but not to a captured image and so i don't know how to do it.
[STAThread]
public System.Drawing.Bitmap Capture()
{
isInCapture = true;
try
{
// init
bool captureDone = false;
bitmap = new System.Drawing.Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb);
// the capture needs some time
for (int i = 0; !captureDone; i++)
{
try
{
//capture
duplicatedOutput.AcquireNextFrame(-1, out duplicateFrameInformation, out screenResource);
// only for wait
if (i > 0)
{
using (var screenTexture2D = screenResource.QueryInterface<Texture2D>())
device.ImmediateContext.CopyResource(screenTexture2D, screenTexture);
mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, MapFlags.None);
mapDest = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, captureRect.Width, captureRect.Height),
ImageLockMode.WriteOnly, bitmap.PixelFormat);
sourcePtr = mapSource.DataPointer;
destPtr = mapDest.Scan0;
// set x position offset to rect.x
int rowPitch = mapSource.RowPitch - offsetX;
// set pointer to y position
sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch * captureRect.Y);
for (int y = 0; y < captureRect.Height; y++) // needs to speed up!!
{
// set pointer to x position
sourcePtr = IntPtr.Add(sourcePtr, offsetX);
// copy pixel to bmp
Utilities.CopyMemory(destPtr, sourcePtr, pWidth);
// incement pointert to next line
sourcePtr = IntPtr.Add(sourcePtr, rowPitch);
destPtr = IntPtr.Add(destPtr, mapDest.Stride);
}
bitmap.UnlockBits(mapDest);
device.ImmediateContext.UnmapSubresource(screenTexture, 0);
captureDone = true;
}
screenResource.Dispose();
duplicatedOutput.ReleaseFrame();
}
catch//(Exception ex) // catch (SharpDXException e)
{
//if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code)
//{
// // throw e;
//}
return new Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb);
}
}
}
catch
{
return new Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb);
}
isInCapture = false;
return bitmap;
}
It would be really great to get a little start assist from someone who willing to help.
I've found some shaders on inet but it is written for opengl (https://github.com/dghost/glslRiftDistort/tree/master/libovr-0.4.x/glsl110). Can i use the also for directx (sharpdx)?
Thanks forward for any help!
Now I've never used DirectX myself, but I suppose you'll need to use HLSL instead of GLSL (which should be fairly similar though). The idea is that you'll have to load your "screenshot" into a texture buffer, as an input to your fragment shader (pixel shader). Fragment shaders are deceptively easy to understand, it's just a piece of code (written in GLSL or HLSL) looking very much like a subset of C to which a few math functions has been added (vector and matrices manipulation mostly) executed for every single pixel to be rendered.
The code should be fairly simple, you'll take the current pixel position, apply the barrel distortion transformation to it's coordinates, then look up that coordinate in your screenshot texture. The transformation should look something like that :
vec2 uv;
/// Barrel Distortion ///
float d=length(uv);
float z = sqrt(1.0 - d * d);
float r = atan(d, z) / 3.14159;
float phi = atan(uv.y, uv.x);
uv = vec2(r*cos(phi)+.5,r*sin(phi)+.5);
Here's a shadertoy link if you wanna play with it and figure out how it works
I have no idea how HLSL handles texture filtering (which pixel you'll get when using floating point values for coordinates), but I'd put my money on bilinear filtering, which may very well give an unpleasant pixelyness to your output. You'll have to look at better filtering methods once you get the distortion working. Shouldn't be anything too complicated, familiarize yourself with HLSL syntax, find how to load your screenshot into a texture in DirectX and get rolling.
Edit : I said barrel distortion but the code is actually for the fisheye effect. Of course both are pretty much identical, the barrel distortion being only on one axis. I believe what you need is the fisheye effect though, it's what is commonly used for HMDs if I'm not mistaken.

WPF Image Collison Detection

I have some code which detects collision ;
public bool DetectCollision(ContentControl ctrl1, ContentControl ctrl2)
{
Rect ctrl1Rect = new Rect(
new Point(Convert.ToDouble(ctrl1.GetValue(Canvas.LeftProperty)),
Convert.ToDouble(ctrl1.GetValue(Canvas.TopProperty))),
new Point((Convert.ToDouble(ctrl1.GetValue(Canvas.LeftProperty)) + ctrl1.ActualWidth),
(Convert.ToDouble(ctrl1.GetValue(Canvas.TopProperty)) + ctrl1.ActualHeight)));
Rect ctrl2Rect = new Rect(
new Point(Convert.ToDouble(ctrl2.GetValue(Canvas.LeftProperty)),
Convert.ToDouble(ctrl2.GetValue(Canvas.TopProperty))),
new Point((Convert.ToDouble(ctrl2.GetValue(Canvas.LeftProperty)) + ctrl2.ActualWidth),
(Convert.ToDouble(ctrl2.GetValue(Canvas.TopProperty)) + ctrl2.ActualHeight)));
ctrl1Rect.Intersect(ctrl2Rect);
return !(ctrl1Rect == Rect.Empty);
}
It detects when 2 rectangles are over. There are images in the given parameter ContentControls. I want to be able to detect if those images intersects not the rectangels. Following images shows whatn I want ;
Then you are not looking for rectangular collision detection but actually pixel-level collision detection and that is going to be much more processing intensive.
On top of the rectangular collision detection that you already have implemented you will have to examine each pixel of both images in the overlapping rectangular region.
In the simplest case, if both of two overlapping pixels have non transparent color then you have a collision.
If you want to complicate things you may want to add thresholds such as: requiring a percentage of overlapping pixels in order to trigger a collision; or setting a threshold for the combined alpha level of the pixels instead of using any non zero value.
You can try converting your images as a geometry object and then you can check if they are colliding correctly. But these images should be as a vector image. To convert images to a vector image, you can check this open source project.
public static Point[] GetIntersectionPoints(Geometry g1, Geometry g2)
{
Geometry og1 = g1.GetWidenedPathGeometry(new Pen(Brushes.Black, 1.0));
Geometry og2 = g2.GetWidenedPathGeometry(new Pen(Brushes.Black, 1.0));
CombinedGeometry cg = new CombinedGeometry(GeometryCombineMode.Intersect, og1, og2);
PathGeometry pg = cg.GetFlattenedPathGeometry();
Point[] result = new Point[pg.Figures.Count];
for (int i = 0; i < pg.Figures.Count; i++)
{
Rect fig = new PathGeometry(new PathFigure[] { pg.Figures[i] }).Bounds;
result[i] = new Point(fig.Left + fig.Width / 2.0, fig.Top + fig.Height / 2.0);
}
return result;
}

How to return a texture from pixel shader in Unity 3d shaderlab?

How to create a simple pixel color shader that say takes a texture, applyes something like masking:
half4 color = tex2D(_Texture0, i.uv.xy);
if(distance(color, mask) > _CutOff)
{
return color;
}
else
{
return static_color;
}
in and returns a texture that can be passed to next shader from c# code in a way like mats[1].SetTexture("_MainTex", mats[0].GetTexture("_MainTex"));?
But... you might not want to do a shader to only modify a texture.
Why not? It is a common practice.
Check out Graphics.Blit. It basically draws a quad with material (including a shader) applied. So you could use your shader to modify a texture. But the texture has to be RenderTexture.
It would be like this:
var mat = new Material(Shader.Find("My Shader"));
var output = new RenderTexture(...);
Graphics.Blit(sourceTexture, output, mat);
sourceTexture in this case will be bound to _MainTex of My Shader.

Why does a valid Texture not reach the Shader? (Direct3D9)

Hello everyone I'm currently trying to create a deferred renderer for my graphics engine using c# and SlimDX. As a resource I use this tutorial which is very helpful eventhough it's intended for XNA.
But right now I'm stuck...
I have my renderer set up to draw all geometry's color, normals and depth to seperate render target textures. This works. I can draw the resulting textures to the restored backbuffer as sprites and I can see that they contain just what they are supposed to. But when I try to pass those Textures to another shader, in this case to create a light map, weirds things happen. Here's how I draw one frame:
public bool RenderFrame(FrameInfo fInfo){
if(!BeginRender()) //checks Device, resizes buffers, calls BeginScene(), etc.
return false;
foreach(RenderQueue queue in fInfo.GetRenderQueues()){
RenderQueue(queue);
}
EndRender(); //currently only calls EndScene, used to do more
ResolveGBuffer();
DrawDirectionalLight(
new Vector3(1f, -1f, 0),
new Color4(1f,1f,1f,1f),
fi.CameraPosition,
SlimMath.Matrix.Invert(fi.ViewProjectionMatrix));
}
private void ResolveGBuffer() {
if(DeviceContext9 == null || DeviceContext9.Device == null)
return;
DeviceContext9.Device.SetRenderTarget(0, _backbuffer);
DeviceContext9.Device.SetRenderTarget(1, null);
DeviceContext9.Device.SetRenderTarget(2, null);
}
private void DrawDirectionalLight(Vector3 lightDirection, Color4 color, SlimMath.Vector3 cameraPosition, SlimMath.Matrix invertedViewProjection) {
if(DeviceContext9 == null || DeviceContext9.Device == null)
return;
DeviceContext9.Device.BeginScene();
_directionalLightShader.Shader.SetTexture(
_directionalLightShader.Parameters["ColorMap"],
_colorTexture);
_directionalLightShader.Shader.SetTexture(
_directionalLightShader.Parameters["NormalMap"],
_normalTexture);
_directionalLightShader.Shader.SetTexture(
_directionalLightShader.Parameters["DepthMap"],
_depthTexture);
_directionalLightShader.Shader.SetValue<Vector3>(
_directionalLightShader.Parameters["lightDirection"],
lightDirection);
_directionalLightShader.Shader.SetValue<Color4>(
_directionalLightShader.Parameters["Color"],
color);
_directionalLightShader.Shader.SetValue<SlimMath.Vector3>(
_directionalLightShader.Parameters["cameraPosition"],
cameraPosition);
_directionalLightShader.Shader.SetValue<SlimMath.Matrix>(
_directionalLightShader.Parameters["InvertViewProjection"],
invertedViewProjection);
_directionalLightShader.Shader.SetValue<Vector2>(
_directionalLightShader.Parameters["halfPixel"],
_halfPixel);
_directionalLightShader.Shader.Technique =
_directionalLightShader.Technique("Technique0");
_directionalLightShader.Shader.Begin();
_directionalLightShader.Shader.BeginPass(0);
RenderQuad(SlimMath.Vector2.One * -1, SlimMath.Vector2.One);
_directionalLightShader.Shader.EndPass();
_directionalLightShader.Shader.End();
DeviceContext9.Device.EndScene();
}
Now when I replace the call to DrawDirectionalLight with some code to draw _colorTexture, _normalTexture and _depthTexture to the screen everything looks ok, but when I use the DrawDirectionalLight function instead I see wild flickering. From the output of PIX it looks like my textures do not get passed to the shader correctly:
Following the tutorial the texture parameters and samplers are defined as follows:
float3 lightDirection;
float3 Color;
float3 cameraPosition;
float4x4 InvertViewProjection;
texture ColorMap;
texture NormalMap;
texture DepthMap;
sampler colorSampler = sampler_state{
Texture = ColorMap;
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter= LINEAR;
MinFilter= LINEAR;
MipFilter= LINEAR;
};
sampler depthSampler = sampler_state{
Texture = DepthMap;
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter= POINT;
MinFilter= POINT;
MipFilter= POINT;
};
sampler normalSampler = sampler_state{
Texture = NormalMap;
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter= POINT;
MinFilter= POINT;
MipFilter= POINT;
};
Now my big question is WHY? There are no error messages printed to debug output.
EDIT:
the rendertargets/textures are created like this:
_colorTexture = new Texture(DeviceContext9.Device,
DeviceContext9.PresentParameters.BackBufferWidth,
DeviceContext9.PresentParameters.BackBufferHeight,
1,
Usage.RenderTarget,
Format.A8R8G8B8,
Pool.Default);
_colorSurface = _colorTexture.GetSurfaceLevel(0);
_normalTexture = new Texture(DeviceContext9.Device,
DeviceContext9.PresentParameters.BackBufferWidth,
DeviceContext9.PresentParameters.BackBufferHeight,
1,
Usage.RenderTarget,
Format.A8R8G8B8,
Pool.Default);
_normalSurface = _normalTexture.GetSurfaceLevel(0);
_depthTexture = new Texture(DeviceContext9.Device,
DeviceContext9.PresentParameters.BackBufferWidth,
DeviceContext9.PresentParameters.BackBufferHeight,
1,
Usage.RenderTarget,
Format.A8R8G8B8,
Pool.Default);
_depthSurface = _depthTexture.GetSurfaceLevel(0);
EDIT 2:
The problems seems to lie in the directionalLightShader itselft since passing other regular textures doesn't work either.
The answer to my problem is as simple as the problem was stupid. The strange behaviour was caused by 2 different errors:
I was just looking at the wrong events in PIX. The textures we passed correctly to the shader but I didn't see it because it was 'hidden' in the BeginPass-event (behind the '+').
The pixel shader which I was trying to execute never got called because vertices of the fullscreen quad I used to render were drawn in clockwise order... my CullMode was also set to clockwise...
Thanks to everyone who read this question!

Color Replacement in XNA C#

I load my textures using
Texture2D.FromFile()
then draw them using
spriteBatch.Draw()
But here's the point: I want to change some colors of the image to another ones. So my questions:
How to change single color of the image to another single color (eg. blue to red).
In fact, what I really want to do is changing group of colors to another group of colors. For example red and similar hues to red to blue and similar hues to blue. You can do this for example in Corel PHOTO-PAINT ("Replace Color").
Please have in mind, that I'm a beginner in XNA.
Best regards,
Jack
EDIT:
Thank you very much for help, guys. Callum's answer is very helpful indeed. But I'm wondering is there a built-in function to solve my second problem, because writing your own may be time-consuming. And I think, that kind of function may be very useful. Something like:
color.SetNewColor(Color color_from, Color color_to, int range)
That kind of function, as I've said before, is built in Corel PHOTO-PAINT. To explain it better, here is the example of what I'm talking about:
link text
So, I only set color_from, color_to and range. I think it works like that: it checks every color of the image, if it is in range of color_from, it is changed to adequate color in hue of color_to.
I assume you mean change individual pixels? In that case use the GetData() and SetData() methods of the Texture2D class.
For example, you can get an array containing the colours of the individual pixels by doing this:
// Assume you have a Texture2D called texture
Color[] data = new Color[texture.Width * texture.Height];
texutre.GetData(data);
// You now have a packed array of Colors.
// So, change the 3rd pixel from the right which is the 4th pixel from the top do:
data[4*texture.Width+3] = Color.Red;
// Once you have finished changing data, set it back to the texture:
texture.SetData(data);
Note you can use the other overloads of GetData() to select only a section.
So, to replace each pixel of a specified colour to another colour:
// Assume you have a Texture2D called texture, Colors called colorFrom, colorTo
Color[] data = new Color[texture.Width * texture.Height];
texutre.GetData(data);
for(int i = 0; i < data.Length; i++)
if(data[i] == colorFrom)
data[i] = colorTo;
texture.SetData(data);
To see if hues are similar, try this method:
private bool IsSimilar(Color original, Color test, int redDelta, int blueDelta, int greenDelta)
{
return Math.Abs(original.R - test.R) < redDelta && Math.Abs(original.G - test.G) < greenDelta && Math.Abs(original.B - test.B) < blueDelta;
}
where *delta is the tolerance of change for each colour channel that you want to accept.
To answer your edit, no there is a built in function, but you can just use a mixture of ideas from the two sections above:
Color[] data = new Color[texture.Width * texture.Height];
texutre.GetData(data);
for(int i = 0; i < data.Length; i++)
if(IsSimilar(data[i], colorFrom, range, range, range))
data[i] = colorTo;
texture.SetData(data);
Moving data between the GPU and CPU by using GetData and SetData is an expensive operation. If there are a limited number of colors, you could use a pixel shader effect when rendering to the screen. You can pass an effect to SpriteBatch.Begin:
sampler2D input : register(s0);
/// <summary>The color used to tint the input.</summary>
/// <defaultValue>White</defaultValue>
float4 FromColor : register(C0);
/// <summary>The color used to tint the input.</summary>
/// <defaultValue>Red</defaultValue>
float4 ToColor : register(C1);
/// <summary>Explain the purpose of this variable.</summary>
/// <minValue>05/minValue>
/// <maxValue>10</maxValue>
/// <defaultValue>3.5</defaultValue>
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 Color;
Color= tex2D(input , uv.xy);
if (Color.r == FromColor.r && Color.g == FromColor.g && Color.b == FromColor.b)
return ToColor;
return Color;
}
technique Technique1
{
pass Pass1
{
PixelShader = compile ps_2_0 main();
}
}
Create your effect in your LoadContent method:
colorSwapEffect = Content.Load<Effect>(#"Effects\ColorSwap");
colorSwapEffect.Parameters["FromColor"].SetValue(Color.White);
colorSwapEffect.Parameters["ToColor"].SetValue(Color.Red);
And pass the effect to your call to SpriteBatch.Begin():
sprite.Begin(0, BlendState.Opaque, SamplerState.PointWrap,
DepthStencilState.Default, RasterizerState.CullNone, colorSwapEffect);
For what you really want to do, you can swap the red and blue channels even more easily. Change your pixel shader's main() function to this, which swaps b (blue) and r (red):
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 Color;
Color= tex2D(input , uv.xy);
return float4(Color.b, Color.g, Color.r, Color.a);
}
Callum's solution is powerful and flexible.
A more limited solution that is slightly easier to implement is to leverage the spriteBatch color parameter.
The variables
Texture2D sprite; //Assuming you have loaded this somewhere
Color color = Color.Red; //The color you want to use
Vector2 position = new Vector2(0f, 0f); //the position to draw the sprite
The drawing code
//Start the spriteBatch segment, enable alpha blending for transparency
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
//Draw our sprite at the specified position using a specified color
spriteBatch.Draw(sprite, position, color);
//end the spritebatch
spriteBatch.End();
If your sprite is all white, then using this method will turn your sprite red. Also, make sure you are using a file format with transparency in it, PNG is a favorite.
Callum hit it on the head if you are changing the color of 2D images as it seems you are - but as you can see you actually need to determine the actual pixel you want to modify and edit it rather than "replace yellow with green" for example.
The same logic could be used to do this replacement (simply loop through the pixels of the image and check the color - I can say that be wary when editing textures like this though as they seemed to cause some pretty serious spikes in performance depending on what was done and how often. I didn't fully investigate but I think it was causing quite a bit of garbage collection.
this works for me:
protected override void Initialize()
{
sprite = Content.Load<Texture2D>("Parado");
Color[] data = new Color[sprite.Width * sprite.Height];
sprite.GetData(data);
// new color
Color novaCor =Color.Blue;
for (int i = 0; i < data.Length; i++)
{
// cor roxa no desenho
if (data[i].R == 142
&& data[i].G == 24
&& data[i].B == 115)
{
data[i] = novaCor;
}
}
sprite.SetData<Color>(data);
posicaoNinja = new Vector2(0, 200);
base.Initialize();
}

Categories