首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XNA中的ColorMatrix等效项

XNA中的ColorMatrix等效项
EN

Stack Overflow用户
提问于 2010-04-11 07:11:42
回答 3查看 775关注 0票数 2

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

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

在XNA中如何做到这一点?有没有我可以使用的通用着色器?任何帮助都会被感谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-06-20 12:56:28

好的,基于您的代码(here),它与ColorMatrix不完全相同(但这应该让您很好地了解如何添加完整的矩阵功能,如果您想要的话),下面是一个可以在XNA上工作的版本:

首先,下载Sprite Effects sample。这将省去我进行设置的麻烦。我只是要替换掉去饱和度的效果。

这是一个像素着色器,几乎和你自己的一样。将"desaturate.fx“的内容替换为:

代码语言:javascript
复制
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中提到的那样。)

代码语言:javascript
复制
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值的sprites!(实际上colorMultiply有点多余,因为您可以只使用sprite颜色作为colorMultiply,您可以针对每个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是一个很好的起点。

票数 2
EN

Stack Overflow用户

发布于 2010-04-12 02:53:46

您可以使用自定义像素着色器非常轻松地进行这种颜色操作。例如,使用如下所示的像素着色器:

代码语言:javascript
复制
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;
}

在XNA4.0中,使用带有SpriteBatch类的自定义着色器是一件非常容易的事情,:

肖恩·哈格里夫斯的

票数 1
EN

Stack Overflow用户

发布于 2010-06-19 10:13:14

下面是一个使用Silverlight和WPF的解决方案:

代码语言:javascript
复制
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上工作的人回答。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2615379

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档