Search code examples
c#xnahlsleffectspritebatch

C# XNA EffectPass.Apply() not doing anything


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.


Solution

  • 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.