0

What I would like to do is to be able to draw a specific set of sprites within a spriteBatch with additive blending. The problem is that the draw order that they're drawn in needs to be preserved and I can't draw everything else in the SpriteBatch with additive blending, so I can't just do this:

spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);
    //Draw some stuff here
spriteBatch.End();

spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.Additive);
    //Draw stuff with additive blending here
spriteBatch.End();

So my solution would be to write a shader to do what I need and just do this:

spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);
    //Draw some stuff here

    foreach(EffectPass pass in AdditiveShader.CurrentTechnique.Passes)
    {
        pass.Apply()
        //Draw stuff with additive shader applied here
    }
spriteBatch.End()

But pass.Apply() is literally doing nothing. Even if I try just using a BasicEffect and have it rotate a few degrees, it's doing nothing. The only way I can get it to do anything is to call it like this:

spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend, 
                  null, null, null, AdditiveShader);

Then it actually does something to sprites, but that doesn't really help me because I want to only apply it to specific sprites and still retain the draw order.

What am I doing wrong when using pass.Apply()? Is there a way to draw a set of sprites with additive blending and another set with alpha blending and still keep the draw order? Any help would be greatly appreciated. Thanks.

EDIT: For clarification, I'm working in 2D.

Salah Akbari
  • 39,330
  • 10
  • 79
  • 109
Darthmarshie
  • 87
  • 1
  • 11
  • You tried to use a different `RenderTarget` than the back buffer? That way you can change any state (blend, depth, stencil) wihout interference and then just render the results one after another. – LInsoDeTeh Sep 09 '15 at 09:15
  • @LInsoDeTeh This part of the code is already rendering to a `RenderTarget2D` called `GameRenderTarget`. Then I layer up all my targets and push them to the backbuffer right at the end of the draw method. Can you maybe give a code example of what you mean? I don't understand exactly. Do you mean I can change the state of the `spriteBatch` without it interfering? Example code would be great. – Darthmarshie Sep 09 '15 at 10:59
  • What I mean is you can do something like (pseudo code as I am not at home): graphicsDevice.SetRenderTarget(target1); graphicsDevice.BlendState = blendState1, graphicsDevice.StencilState = stencilState1; spriteBatch.Begin(); DrawWhatever(); spriteBatch.End(); graphicsDevice.SetRenderTarget(target2); graphicsDevice.BlendState = blendState2, graphicsDevice.StencilState = stencilState2; spriteBatch.Begin(); DrawSomethingElse(); spriteBatch.End(); graphicsDevice.SetRenderTarget(null); spriteBatch.Begin(); spriteBatch.Draw((Texture)target1); spriteBatch.Draw((Texture)target2); spriteBatch.End(); – LInsoDeTeh Sep 09 '15 at 11:10

1 Answers1

0

OK, so what I found (Thanks to Shawn Hargreaves - http://blogs.msdn.com/b/shawnhar/archive/2010/04/05/spritebatch-and-custom-renderstates-in-xna-game-studio-4-0.aspx) is that I can use GraphicsDevice.BlendState = BlendState.Additive to change the BlendState on the fly.

So what I did was this:

spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Alpha);
    //Draw with alpha blending here

    GraphicsDevice.BlendState = BlendState.Additive;        
    //Draw specific sprites with additive blending here

    GraphicsDevice.BlendState = BlendState.Alpha; //Revert the blendstate to Alpha
    //Draw more stuff here with alpha blending

spriteBatch.End();

The problem is that the SpriteSortMode for the spriteBatch has to be set to Immediate or GraphicsDevice.BlendState = BlendState.Additive will do nothing.

So I suppose I'll have to use a custom DepthStencilState to replicate the functionality of SpriteSortMode.FrontToBack.

Darthmarshie
  • 87
  • 1
  • 11