在XNA中,如何实现应用System.Drawing.Imaging.ColorMatrix的相同效果?下面的文章展示了我如何渲染我的精灵,但它使用GDI +:
如何在XNA中完成?我可以使用通用着色器吗?任何帮助都会受到重视。
答案 0 :(得分:2)
好的,基于你的代码(here),这与ColorMatrix不完全相同(但这应该可以让你很好地了解如何根据需要添加完整的矩阵功能),这里是一个适用于XNA的版本:
首先,下载Sprite Effects sample。这将节省我通过设置的东西。我只是要取代去饱和效果。
这是一个与您自己的像素着色器几乎相同的像素着色器。用以下内容替换“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
函数:
(正如Joel Martinez在XNA 4 this code becomes much neater中提到的那样。)
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,你可以改变每个精灵。)
因此,如果每个sprite具有不同的add / multiply值,则必须为每个sprite执行整个SpriteBatch.Begin,Effect.Begin,draw stuff,SpriteBatch.End,Effect.End。
原因是像素着色器及其参数只能按批次as explained in this blog post设置一次。
如果你有很多精灵,每批做一个精灵会很慢!
对此的解决方案(如果你需要那种性能)将是一个自定义精灵批处理器,其自定义顶点着色器可以将多种颜色传递给像素着色器。这是可能的,虽然不是微不足道的。一个很好的起点是source code for the shaders used by SpriteBatch。
答案 1 :(得分:1)
您可以使用自定义像素着色器轻松完成此类色彩处理。例如,使用像这样的像素着色器:
sampler2D sampler;
float4 PixShader( float2 tex : TEXCOORD0 ) : COLOR0
{
float4 color;
color = tex2D( sampler, tex);
//do anything you want to the colors
color.r = color.r * 2; // intensify the red component
color.g = color.g * 0.5; // cut all green values in half
// etc.
return color;
}
在XNA 4.0中使用SpriteBatch类的自定义着色器非常容易这么多:
Shawn Hargreaves的 SpriteBatch and custom shaders in XNA Game Studio 4.0
答案 2 :(得分:1)
这是一个适用于Silverlight和WPF的解决方案:
sampler2D input : register(s0);
/// <defaultValue>1.0</defaultValue>
float RMul : register(C0);
/// <defaultValue>1.0</defaultValue>
float GMul : register(C1);
/// <defaultValue>1.0</defaultValue>
float BMul : register(C2);
/// <defaultValue>1.0</defaultValue>
float AMul : register(C3);
/// <defaultValue>0</defaultValue>
float RAdd : register(C4);
/// <defaultValue>0</defaultValue>
float GAdd : register(C5);
/// <defaultValue>0</defaultValue>
float BAdd : register(C6);
/// <defaultValue>0</defaultValue>
float AAdd : register(C7);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 color = tex2D(input, uv);
color = color.rgba * float4(RMul, GMul, BMul, AMul) + float4(RAdd, GAdd, BAdd, AAdd);
return color;
}
我会给第一个调整它以便在XNA上工作的人给出答案。