ColorMatrix在XNA中等效

时间:2010-04-10 23:11:42

标签: c# xna

在XNA中,如何实现应用System.Drawing.Imaging.ColorMatrix的相同效果?下面的文章展示了我如何渲染我的精灵,但它使用GDI +:

http://www.c-sharpcorner.com/UploadFile/mahesh/Transformations0512192005050129AM/Transformations05.aspx

如何在XNA中完成?我可以使用通用着色器吗?任何帮助都会受到重视。

3 个答案:

答案 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上工作的人给出答案。