El problema es que XNA en Windows Phone no tiene soporte de sombreador personalizado, por lo que no puede escribir un sombreador de vértices o sombreadores de píxeles. Sin embargo, puede usar un truco descrito por Catalin Zima que deforma una cuadrícula de vértice para lograr el mismo efecto.
Si no está apuntando a Windows Phone 7, puede usar un truco que describí en mi blog . Copiando los bits relevantes en:
Estas distorsiones requieren 2 imágenes. En primer lugar, necesita toda la escena como un objetivo de renderizado (es decir, Texture2D), así como el objetivo de renderizado de distorsión. Por lo general, usaría un sistema de partículas para llenar el objetivo de renderizado de distorsión; utilizando sprites especiales de distorsión (ejemplo a continuación)
Cada componente de color en el objetivo de distorsión (y los sprites de distorsión) representa lo siguiente:
- R : dx: desplazamiento X - f (x) = mapeo 2x-1 ([0.0f, 1.0f] a [-1.0f, 1.0f]).
- G : dy: desplazamiento de Y - f (x) = mapeo 2x-1.
- B : m: Fuerza Z - f (x) = x mapeo.
Un buen ejemplo de un sprite que se usaría para una onda sería:
Determinar el resultado de una onda es tan simple como sumar las ondas (teniendo en cuenta el mapeo que debe realizar primero en [-1.0f, 1.0f]); porque las ondas en realidad también son aditivas, esto simplemente funciona : obtendrá muy buenas aproximaciones de ondas reales.
Una vez que tenga los dos objetivos de renderizado, puede usar el siguiente sombreador:
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();
}
}
Este es el efecto final:
Esta técnica también debería funcionar para juegos 3D; aunque es posible que deba dedicar más atención al sombreador de partículas y al sombreador de distorsión.