Проблема полягає в тому, що XNA на Windows Phone не підтримує користувальницьку підтримку шейдера, тому ви не можете написати шейдер вершини або піксельний шейдер. Однак ви можете використовувати фокус, описаний Каталіном Зімою, який деформує сітку вершин, щоб досягти такого ж ефекту.
Якщо ви не орієнтуєтесь на 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-ігор; хоча вам, можливо, доведеться приділяти більше уваги шейдеру частинок та шейдеру спотворення.