Проблема в том, что XNA в Windows Phone не имеет поддержки пользовательских шейдеров - поэтому вы не можете написать вершинный или пиксельный шейдер. Тем не менее, вы можете использовать трюк, описанный Catalin Zima, который деформирует сетку вершин для достижения того же эффекта.
Если вы не нацелены на Windows Phone 7, вы можете воспользоваться трюком, который я описал в своем блоге . Копирование соответствующих битов в:
Эти искажения требуют 2 изображения. Во-первых, вам нужна вся сцена в качестве цели рендеринга (т.е. Texture2D), а также цель рендеринга искажения. Обычно вы используете систему частиц для заполнения цели визуализации искажения; используя специальные спрайты искажения (пример ниже).
Каждый компонент цвета в цели искажения (и спрайтах искажения) представляет следующее:
- R : dx: X смещение - f (x) = отображение 2x-1 ([0.0f, 1.0f] до [-1.0f, 1.0f]).
- G : dy: Y смещение - f (x) = 2x-1 отображение.
- B : m: Z прочность - f (x) = x отображение.
Хороший пример спрайта, который будет использоваться для пульсации:
Определить исход ряби так же просто, как сложить волны вместе (помня о том, что нужно сначала выполнить сопоставление с [-1.0f, 1.0f]); поскольку волны в действительности также аддитивны, это просто работает - вы получите очень хорошие приближения реальных волн.
Когда у вас есть две цели рендеринга, вы можете использовать следующий шейдер:
Texture InputTexture; // The distortion map.
Texture LastTexture; // The actual rendered scene.
sampler inputTexture = sampler_state
{
texture = <InputTexture>;
magFilter = POINT;
minFilter = POINT;
mipFilter = POINT;
};
sampler lastTexture = sampler_state
{
texture = <LastTexture>;
magFilter = LINEAR;
minFilter = LINEAR;
mipFilter = LINEAR;
addressU = CLAMP;
addressV = CLAMP;
};
struct VS_OUTPUT
{
float4 Position : POSITION;
float2 TexCoords : TEXCOORD0;
};
float4 Distort (VS_OUTPUT Input)
{
float4 color1;
float4 color2;
float2 coords;
float mul;
coords = Input.TexCoords;
color1 = tex2D(inputTexture, coords);
// 0.1 seems to work nicely.
mul = (color1.b * 0.1);
coords.x += (color1.r * mul) - mul / 2;
coords.y += (color1.g * mul) - mul / 2;
color2 = tex2D(lastTexture, coords);
return color2;
}
float4 RunEffects (VS_OUTPUT Input) : COLOR0
{
float4 color;
color = Distort(Input);
return color;
}
technique Main
{
pass P0
{
PixelShader = compile ps_2_0 RunEffects();
}
}
Это конечный эффект:
Эта техника также должна работать для 3D-игр; хотя, возможно, вам придется больше думать о шейдере частиц и шейдере искажений.