Le problème est que XNA sur Windows Phone ne prend pas en charge les shaders personnalisés - vous ne pouvez donc pas écrire de vertex shader ou de pixel shader. Cependant, vous pouvez utiliser une astuce décrite par Catalin Zima qui déforme une grille de sommets pour obtenir le même effet.
Si vous ne ciblez pas Windows Phone 7, vous pouvez utiliser une astuce que j'ai décrite sur mon blog . Copie des bits pertinents dans:
Ces distorsions nécessitent 2 images. Tout d'abord, vous avez besoin de la scène entière comme cible de rendu (c'est-à-dire Texture2D) ainsi que de la cible de rendu de distorsion. En règle générale, vous utiliseriez un système de particules pour remplir la cible de rendu de distorsion; en utilisant des sprites de distorsion spéciaux (exemple ci-dessous).
Chaque composante de couleur dans la cible de distorsion (et les sprites de distorsion) représente les éléments suivants:
- R : dx: décalage X - f (x) = mappage 2x-1 ([0.0f, 1.0f] à [-1.0f, 1.0f]).
- G : dy: décalage Y - f (x) = mappage 2x-1.
- B : m: force Z - f (x) = cartographie x.
Un bon exemple de sprite qui serait utilisé pour une ondulation serait:
Déterminer le résultat d'une ondulation est aussi simple que d'ajouter les vagues ensemble (en gardant à l'esprit le mappage que vous devez effectuer en premier sur [-1.0f, 1.0f]); parce que les vagues en réalité sont également additives, cela fonctionne - vous obtiendrez de très bonnes approximations des vagues réelles.
Une fois que vous avez les deux cibles de rendu, vous pouvez utiliser le shader suivant:
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();
}
}
C'est l'effet final:
Cette technique devrait également fonctionner pour les jeux 3D; bien que vous deviez peut-être consacrer plus de réflexion au shader de particules et au shader de distorsion.