Эквивалент ColorMatrix в XNA - PullRequest
       10

Эквивалент ColorMatrix в XNA

2 голосов
/ 11 апреля 2010

В XNA, как я могу добиться того же эффекта от применения System.Drawing.Imaging.ColorMatrix? В следующей статье показано, как я хотел бы визуализировать свои спрайты, но в нем используется GDI +:

http://www.c -sharpcorner.com / UploadFile / Махеш / Transformations0512192005050129AM / Transformations05.aspx

Как это можно сделать в XNA? Можно ли использовать шейдер общего назначения? Любая помощь будет оценена.

Ответы [ 3 ]

2 голосов
/ 20 июня 2010

ОК, на основе вашего кода ( здесь ), который не совсем совпадает с 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 .

1 голос
/ 19 июня 2010

Вот решение, которое работает с 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.

1 голос
/ 11 апреля 2010

Вы можете использовать пользовательский пиксельный шейдер, чтобы очень легко выполнять подобные манипуляции с цветом. Например, возьмите пиксельный шейдер так:

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 и пользовательские шейдеры в XNA Game Studio 4.0 от Шона Харгривза

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...