ОК, на основе вашего кода ( здесь ), который не совсем совпадает с ColorMatrix (но это должно дать вам хорошее представление о том, как добавить полную функциональность матрицы, если вы хотите), здесь версия, которая будет работать на XNA:
Прежде всего, скачайте образец Sprite Effects . Это спасет меня от настройки. Я просто собираюсь заменить эффект Desaturate.
Вот пиксельный шейдер, который почти такой же, как ваш. Заменить содержимое "desaturate.fx" следующим:
sampler TextureSampler : register(s0);
float4 colorMultiply = float4(1, 1, 1, 1);
float4 colorAdd = float4(0, 0, 0, 0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
// Look up the texture color.
float4 tex = tex2D(TextureSampler, texCoord);
// Perform scaling and addition and return
return color * tex * colorMultiply + colorAdd;
}
technique ColorMatrix { pass Pass1 { PixelShader = compile ps_2_0 PixelShader(); } }
А теперь замените функцию DrawDesaturate
на:
(Как упоминает Джоэл Мартинес, в XNA 4 этот код становится намного точнее .)
void DrawDesaturate(GameTime gameTime)
{
Effect colorMulAddEffect = desaturateEffect; // reusing desaturateEffect to keep this short!
float pulsate = Pulsate(gameTime, 4, 0, 1);
spriteBatch.Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.None);
colorMulAddEffect.Parameters["colorMultiply"].SetValue(new Vector4(1.5f, 1f, pulsate, 1f));
colorMulAddEffect.Parameters["colorAdd"].SetValue(new Vector4(-0.5f, 1-pulsate, 0f, 0f));
colorMulAddEffect.Begin();
colorMulAddEffect.CurrentTechnique.Passes[0].Begin();
spriteBatch.Draw(glacierTexture, FullscreenRectangle(), Color.White);
spriteBatch.End();
colorMulAddEffect.CurrentTechnique.Passes[0].End();
colorMulAddEffect.End();
}
Теперь есть один основной при условии с этим кодом - вы не можете пакетировать спрайты с различными значениями colorMultiply и colorAdd! (На самом деле colorMultiply немного избыточен, так как вы можете просто использовать цвет спрайта как colorMultiply, который вы можете изменить для каждого спрайта.)
Так что, если у каждого спрайта есть разные значения для добавления / умножения, вам нужно будет выполнить весь SpriteBatch.Begin, Effect.Begin, нарисовать вещи, SpriteBatch.End, Effect.End для каждого спрайта.
Причина этого в том, что пиксельный шейдер и его параметры могут быть установлены только один раз для каждой партии , как описано в этом сообщении в блоге .
Выполнение одного спрайта на пакет будет медленным, если у вас много спрайтов!
Решением этой проблемы (если вам нужна такая производительность) будет создание настраиваемого дозатора спрайтов с настраиваемым вершинным шейдером, который может передавать более одного цвета в пиксельный шейдер. Это возможно, хотя и нетривиально. Хорошей отправной точкой будет исходный код для шейдеров, используемых SpriteBatch .