Использование эффекта для вуали войны

Я пытаюсь применить вуаль войны к областям на экране, не в настоящее время видимом плееру. Я делаю это путем рендеринга игрового содержания в одном RenderTarget и вуаль войны в другого, и затем я объединяю их с файлом эффектов, который подражает от игры RenderTarget и альфа от вуали войны представляет цель. FOW RenderTarget является черным, где FOW появляется, и белый, где он не делает.

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

Прежде, чем применить эффект я очищаю backbuffer устройства белому. То, когда я пытаюсь очиститься, это к черному цвету, не вуали войны появляется вообще, который я принимаю, является продуктом альфы, смешивающейся с черным цветом. Это работает на все другие цвета, однако - предоставление получающегося экрана оттенка того цвета.

Как делают меня archieve черная вуаль в то время как все еще способность сделать альфу, смешивающуюся между двумя целями рендеринга?

Код рендеринга для применения FOW:

private RenderTarget2D mainTarget;
private RenderTarget2D lightTarget;

   private void CombineRenderTargetsAndDraw()
    {
        batch.GraphicsDevice.SetRenderTarget(null);
        batch.GraphicsDevice.Clear(Color.White);

        fogOfWar.Parameters["LightsTexture"].SetValue(lightTarget);

        batch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
        fogOfWar.CurrentTechnique.Passes[0].Apply();
        batch.Draw(
            mainTarget,
            new Rectangle(0, 0, batch.GraphicsDevice.PresentationParameters.BackBufferWidth, batch.GraphicsDevice.PresentationParameters.BackBufferHeight),
            Color.White
        );

        batch.End();
    }

Файл эффектов я использую для применения FOW:

texture LightsTexture;

sampler  ColorSampler  : register(s0);

sampler LightsSampler = sampler_state{
    Texture = <LightsTexture>;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
};

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float2 tex = input.TexCoord;

    float4 color = tex2D(ColorSampler, tex);
    float4 alpha = tex2D(LightsSampler, tex);

    return float4(color.r, color.g, color.b, alpha.r);
}

technique Technique1
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}
9
задан Joel Martinez 18 May 2010 в 01:52
поделиться

2 ответа

Я не слишком глубоко изучал XNA и не могу установить его в данный момент, чтобы проверить с CTP версии 4.0, но из чтения документации похоже, что вы удваиваете. Насколько я понимаю, BlendState.AlphaBlend заставляет SpriteBatch альфа-смешивать каждый отрисованный спрайт.

Согласно документации он использует настройки по умолчанию

ColorSourceBlend = Blend.One,
AlphaSourceBlend = Blend.One,

ColorDestinationBlend = Blend.InverseSourceAlpha,
AlphaDestinationBlend = Blend.InverseSourceAlpha,

Которые должны иметь следующее влияние:

Один: Каждый компонент цвета умножается на (1, 1, 1, 1, 1).

InverseSourceAlpha: Каждый компонент цвета умножается на обратную величину альфа-значения источника. Этот можно представить как (1 - As, 1 - As, 1 - As, 1 - As), где As - альфа-значение значение назначения.

Таким образом, если вы используете Blend.AlphaBlend, вы можете очистить задний буфер до черного цвета и затем рендерить только спрайты карты, непосредственно понижая альфу там, где она должна быть затемнена. Это просто обесцветит пиксели карты, которые "покрыты" FOW, заставляя их альфа-смешиваться с черным цветом заднего буфера.

Если вы хотите использовать шейдерный подход, вы можете альфа-смешивать шейдер между двумя целями рендеринга. Я немного не понял из вашего объяснения, как именно вы хотите смешивать. Вы говорите, что хотите сделать альфа-смешение, но ваша цель рендеринга FOW черная там, где есть туман, и белая там, где его нет. Если вы используете альфа для управления смешиванием, цвет тумана должен быть однородным (или текстурированным, в зависимости от ситуации) по всей цели рендеринга, в соответствии с тем, какой внешний вид вы хотите получить. Скажем, вы хотите черный туман, ваши цвета должны быть (0, 0, 0) по всей цели рендеринга, а значение альфа должно меняться в зависимости от того, где вы хотите его показать.

Используя этот подход, вы можете изменить ваш шейдер на что-то вроде следующего:

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float2 tex = input.TexCoord;

    float4 color = tex2D(ColorSampler, tex);
    float4 fow = tex2D(LightsSampler, tex);

    // color * inverse of FOW alpha + FOW * FOW alpha
    return float4(color.r * (1-fow.a) + fow.r * fow.a,
                  color.g * (1-fow.a) + fow.g * fow.a,
                  color.b * (1-fow.a) + fow.b * fow.a,
                  1);
}

Я давно не занимался шейдерами на HLSL, но я уверен, что это можно написать гораздо проще. В любом случае, если FOW черный (и back buffer очищен до черного, и вы не накладываете различные спрайты с альфа-смешением друг на друга - см. ответ Джоэла), этот подход не отличается от прямой установки альфа спрайта карты на основе наличия или отсутствия FOW.

3
ответ дан 3 November 2019 в 07:46
поделиться

Похоже, вы столкнулись с ситуацией, которую Шон Харгривз описал в этом сообщении в блоге:
Предварительно умноженная альфа и композиция изображения

Попробуйте переключиться на предварительно умноженную альфа , как он предлагает, и позвольте нам известен результат: -)

1
ответ дан 3 November 2019 в 07:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: