# How to set multiple times, in a single spritebatch, the same pixel shader parameter

I make a test with Effect class in XNA and I want to set multiple times the same parameters (MyParameter in below code).

My code is :

[...]
//In Engine class

spriteBatch.Begin(
SpriteSortMode.Deferred,
BlendState.AlphaBlend,
SamplerState.PointWrap,
DepthStencilState.Default,
RasterizerState.CullNone,

[...]

//in drawable class
foreach(//big loop) {
spriteBatch.Draw(
SpriteSheet,
ScreenRect,
sprite_to_draw.Rectangle,
color,
rotation,
Scene.getInstance().Camera.Position,
sprite_to_draw.SpriteEffect,
layer
);
}

[...]

//In Engine class
spriteBatch.End();
[...]


But on my screen it look like the Parameter "MyParameter" is not overwrite.

So can I overwrite it and If yes do you know how ?

Thanks

• I try Scene.getInstance().ShaderEffect.Parameters["MyParameter"].GetValueVector4Array(1).SetValue(/*new random vector4*/,0); without success. – Cyril ALFARO Mar 4 '13 at 0:45
• I try bind only one time on a variable in my code, same probleme, no change when I change C# variable. – Cyril ALFARO Mar 4 '13 at 0:57
• If end()/begin() my SpriteBatch it works but perf are lower of course. I'm sure there is an other way to do that... – Cyril ALFARO Mar 4 '13 at 1:18

I'm afraid there is not an easy solution to this problem, because you can not add extra information to the vertices generated by SpriteBatch.

Like Blau said, you can change the SpriteBatch to Immediate mode, or call Begin() and End() every time you change the parameter, but you will get a ton of draw calls and won't be batching anything anymore. I can think of two additional solutions:

1) SpriteBatch.Draw takes a color parameter and stores it inside each vertex of the quads it generates. You can then get this value back in your custom shaders. If you do not need to use the default color tinting, and your only parameter is a float4 like in your example, you could hijack the color parameter for your needs, and override the default pixel shader so that it does not tint the sprite.

float4 main(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
// Do whatever you want with the color parameter
// Sample texture but ignore color because it's not really a color
return tex2D(TextureSampler, texCoord);
}


2) Implement your own SpriteBatch with a custom vertex struture that stores the additional information that you need for the shader, so that you do not need to change parameters between drawing each sprite. You can check the following question for some ideas on how to implement it yourself.

How exactly does XNA's SpriteBatch work?

• Thnaks a lot for your answer, I will check it this evening. – Cyril ALFARO Mar 4 '13 at 13:13
• After our exchange by mail It works ! – Cyril ALFARO Mar 5 '13 at 2:00

if you set SpriteSortMode.Deferred the batch will be executed when Batch.End() is called...

You could use SpriteSortMode.Inmediate but it can hurts the perfomance...

The other options are building your own QuadRenderer or using deferred sort mode and call Begin/End for each parameter you need to pass.

• Thank for the answer, It works in immediate render but performance are horrible... I don't know yet how QuadRenderer can help me, where is it and how to build it. There is really no other method to pass a var in shader depending on object ? It looks like a big limitation so I think I didnt get it... – Cyril ALFARO Mar 4 '13 at 9:10
• A quad renderer is an own implementation of spritebatch... ;) – Blau Mar 4 '13 at 9:33
• I did a kind of in OpengGL with LWJGL, code my own renderer to have only one pass to draw all sprite. But spriteBatch have deferred renderer which make this already. I don't know if it can help me to make my own one. But an other param of draw function on spritebatch is Color params, I know that I can change this filter but how it works ? It's a shader ? If yes do you know how they change this to the pipeline renderer ? – Cyril ALFARO Mar 4 '13 at 9:48