[.net] XNA Drawing Sprites

Started by
16 comments, last by alex_myrpg 16 years, 11 months ago
Hi - I am currently trying to use a SpriteBatch to draw a sprite using a certain render state in XNA. I call it like this, for example: _spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.SaveState) ' Set render state to invert cursor pixels. Me.GraphicsDevice.RenderState.AlphaBlendEnable = True Me.GraphicsDevice.RenderState.SeparateAlphaBlendEnabled = True Me.GraphicsDevice.RenderState.BlendFunction = BlendFunction.Add Me.GraphicsDevice.RenderState.SourceBlend = ??? Me.GraphicsDevice.RenderState.DestinationBlend = ??? _spriteBatch.Draw(_currentCursor.Value.Texture, mouseVector, Color.White) _spriteBatch.End() This code is used to draw a cursor - I want it to draw like a cursor does in Windows - it draws normally if the background is white, but when it's dark it inverts the colour of the source image (cursor). I think this is the correct description, but you can see for yourself by putting the edit bar cursor over a textbox (over whitespace and over text). Thanks in advance! [Edited by - alex_myrpg on May 19, 2007 9:20:21 AM]
Advertisement
I'm dense, I don't get what you're trying to do. Do you have a sample screenshot of the two states you're trying to render?

Former Microsoft XNA and Xbox MVP | Check out my blog for random ramblings on game development

Thanks for your reply... sorry I can't really take a screenshot since Windows doesn't capture the cursor along with the screen. If you look closely whenever you put your mouse cursor *over text* in a text box, then you'll see how the cursor coloru inverts over the black (or rather non-white) pixels. I'm just wondering: a) what SourceBlend and DestinationBlend enums to set, b) is there something else I need to do to get this effect?
Actually when you use SpriteBlendMode.AlphaBlend, the render states are already set up to do typical alpha blending (with SourceBlend = SourceAlpha and DestBlend = InverseSourceAlpha). So by just using that SpriteBlendMode and a cursor image with a transparent background (PNG, TGA etc), things should work out just fine and you don't need to worry about setting additional renderstates manually.

Hope this helps :)
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
Thanks, but what I actually need is the *inversion* of the source pixels... let me try to demonstrate please:

0 = white
1 = black

Source pixels (i.e. of the cursor)

0 0 1 1 1 1 1 0 0 < edit-bar or 'I' shaped cursor
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 1 1 1 1 1 0 0

Destination pixels (i.e. text already drawn to screen, using another SpriteBatch)

0 0 1 1 1 1 0 0 0 < letter 'B'
0 0 1 0 0 0 1 0 0
0 0 1 0 0 0 1 0 0
0 0 1 0 0 0 1 0 0
0 0 1 1 1 1 0 0 0
0 0 1 0 0 0 1 0 0
0 0 1 0 0 0 1 0 0
0 0 1 0 0 0 1 0 0
0 0 1 1 1 1 0 0 0

The result that I want should appear like:

0 0 0 0 0 0 1 0 0 < blended result - pixels of B are
0 0 1 0 1 0 1 0 0 inverted wherever the 'I' pixels are.
0 0 1 0 1 0 1 0 0
0 0 1 0 1 0 1 0 0
0 0 1 1 0 1 0 0 0
0 0 1 0 1 0 1 0 0
0 0 1 0 1 0 1 0 0
0 0 1 0 1 0 1 0 0
0 0 0 0 0 0 1 0 0

Thanks for any suggestions... :)
Is it good enough if the cursor simply inverts whatever it's over? I.E. black becomes white, white becomes black, and everything in between is inverted?

If so, you can do it like this:

graphics.GraphicsDevice.RenderState.BlendFunction = BlendFunction.ReverseSubtract;
graphics.GraphicsDevice.RenderState.AlphaSourceBlend = Blend.One;
graphics.GraphicsDevice.RenderState.AlphaDestinationBlend = Blend.One;

This means that your color function is:

FinalColor = DestColor - CursorColor

So on pixels where CursorColor is black, there's no change to the color, and where CursorColor is white, the color is inverted.

You can play around with effects by changing the Source and Dest factors, but you probably want to use ReverseSubtract or Subtract as your BlendFunction.
Thanks again... I just tried that code out using Subtract and ReverseSubtract, but with Subtract it appears the same as with Add, and with ReverseSubtract nothing shows up at all... :S Please ask if you need more info.
What I did to get inverted colors was to set my source blend to InverseDestinationColor and my destination blend was set to InverseSourceColor. That seemed to do the trick for me, at least it looks inverted on my stuff (i.e. black is white, white is black). You can see the effect on my cross hair lines for my sprite editor, the screenshots are in my journal (yes, shameless plug, but it applies).

It should be noted that I'm using MDX and not XNA, there should be no difference in this respect, but who knows what goes on under the hood.

I'm not sure if this will work with sprites that use textures with an alpha channel or not, I haven't really tried, but I'm sure messing around with the blend states will eventually yield a workable combination. And you could always use the alpha mask to crop away unused portions of the sprite while still having the blending set to inverse color.

Edit:
I just tried it out using a sprite with transparent edges (alpha = 0), and it seems to work:


[Edited by - Tape_Worm on May 15, 2007 1:32:12 PM]
Thanks a lot! I'll try it out more, but at first look it only seems to work when I use SpriteMode.Normal. I'll reply with new info tomorrow...
Tape_Worm, I've tried out your idea now but unfortunately it doesn't fully work - if I use SpriteBlendMode.None, it's all fine - but I need cursors to be transparent as well as inverting, so I'm using SpriteBlendMode.AlphaBlend. With this, XNA seems to use a mixture of both blend modes but neither of them work correctly. Perhaps you understand what's going on here? Thanks so far...

This topic is closed to new replies.

Advertisement