O problema é que o XNA no Windows Phone não possui suporte para sombreador personalizado - portanto, você não pode escrever um sombreador de vértice ou sombreador de pixel. No entanto, você pode usar um truque descrito por Catalin Zima que deforma uma grade de vértices para obter o mesmo efeito.
Se você não está direcionando o Windows Phone 7, pode usar um truque que descrevi no meu blog . Copiando os bits relevantes em:
Essas distorções requerem 2 imagens. Primeiro, você precisa de toda a cena como destino de renderização (ou seja, Texture2D), bem como o destino de renderização de distorção. Normalmente, você usaria um sistema de partículas para preencher o alvo de renderização da distorção; usando sprites especiais de distorção (exemplo abaixo).
Cada componente de cor no alvo de distorção (e sprites de distorção) representa o seguinte:
- R : deslocamento dx: X - f (x) = mapeamento 2x-1 ([0,0f, 1,0f] a [-1,0f, 1,0f]).
- G : dy: deslocamento Y - f (x) = mapeamento 2x-1.
- B : m: força Z - f (x) = x mapeamento.
Um bom exemplo de um sprite que seria usado para uma ondulação seria:
Determinar o resultado de uma ondulação é tão simples quanto somar as ondas (tendo em mente o mapeamento necessário primeiro para [-1.0f, 1.0f]); porque as ondas na realidade também são aditivas, isso simplesmente funciona - você terá boas aproximações das ondas reais.
Depois de ter os dois destinos de renderização, você pode usar o seguinte 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 é o efeito final:
Essa técnica também deve funcionar para jogos em 3D; embora você precise dedicar mais atenção ao sombreador de partículas e ao sombreamento por distorção.