Il problema è che XNA su Windows Phone non ha il supporto shader personalizzato, quindi non è possibile scrivere uno shader di vertice o pixel shader. Tuttavia, puoi usare un trucco descritto da Catalin Zima che deforma una griglia di vertici per ottenere lo stesso effetto.
Se non stai prendendo di mira Windows Phone 7, puoi usare un trucco che ho descritto sul mio blog . Copia dei bit rilevanti in:
Queste distorsioni richiedono 2 immagini. Innanzitutto è necessario l'intera scena come obiettivo di rendering (ad esempio Texture2D) e l'obiettivo di rendering della distorsione. In genere si utilizza un sistema di particelle per riempire il target di rendering della distorsione; usando speciali sprite di distorsione (esempio sotto).
Ogni componente di colore nel target di distorsione (e sprite di distorsione) rappresenta quanto segue:
- R : dx: offset X - f (x) = mappatura 2x-1 (da [0.0f, 1.0f] a [-1.0f, 1.0f]).
- sol : dy: offset Y - f (x) = mappatura 2x-1.
- B : m: forza Z - f (x) = x mappatura.
Un buon esempio di uno sprite che sarebbe usato per un'ondulazione sarebbe:
Determinare il risultato di un'ondulazione è semplice come sommare le onde (tenendo presente la mappatura che è necessario eseguire prima su [-1.0f, 1.0f]); perché le onde in realtà sono anche questo additivo funziona e otterrai ottime approssimazioni delle onde reali.
Una volta che hai i due target di rendering puoi usare il seguente shader:
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();
}
}
Questo è l'effetto finale:
Questa tecnica dovrebbe funzionare anche per i giochi 3D; anche se potresti dover dedicare più pensiero allo shader di particelle e allo shader di distorsione.