代码之家  ›  专栏  ›  技术社区  ›  Charles

xna中的色矩阵等价

  •  2
  • Charles  · 技术社区  · 16 年前

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

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

    在XNA怎么做?我能用一个通用的遮影器吗?任何帮助都是值得的。

    3 回复  |  直到 16 年前
        1
  •  2
  •   Community Mohan Dere    9 年前

    好的,根据你的代码( 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 功能如下:

    (正如乔尔·马丁内斯提到的, 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,您可以为每个精灵更改颜色。)

    因此,如果每个精灵有不同的加/乘值,则必须对每个精灵执行整个spritebatch.begin,effect.begin,draw stuff,spritebatch.end,effect.end操作。

    原因是像素着色器及其参数只能在每个批中设置一次 as explained in this blog post .

    如果你有很多雪碧,每批做一个雪碧会很慢!

    解决这个问题的方法(如果您需要这种性能)是制作一个自定义的sprite批处理程序,使用一个自定义的顶点着色器可以将多个颜色传递给像素着色器。这是可能的,虽然不是小事。一个好的起点是 source code for the shaders used by SpriteBatch .

        2
  •  1
  •   Joel Martinez    16 年前

    您可以使用自定义像素明暗器来进行这种颜色操作非常容易。例如,采用如下像素着色器:

    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;
    }
    

    在spritebatch类中使用自定义着色器 这么多 在XNA 4.0中更容易:
    SpriteBatch and custom shaders in XNA Game Studio 4.0 肖恩·哈格里夫斯

        3
  •  1
  •   Charles    16 年前

    以下是一个适用于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的工作。