Das Problem ist, dass XNA unter Windows Phone keine Unterstützung für benutzerdefinierte Shader bietet. Sie können also keinen Vertex-Shader oder Pixel-Shader schreiben. Sie können jedoch einen von Catalin Zima beschriebenen Trick verwenden , der ein Scheitelpunktgitter verformt, um den gleichen Effekt zu erzielen.
Wenn Sie nicht auf Windows Phone 7 abzielen, können Sie einen Trick verwenden, den ich in meinem Blog beschrieben habe . Kopieren der relevanten Bits in:
Diese Verzerrungen erfordern 2 Bilder. Zunächst benötigen Sie die gesamte Szene als Render-Ziel (dh Texture2D) sowie das Verzerrungs-Render-Ziel. Normalerweise verwenden Sie ein Partikelsystem, um das Verzerrungs-Rendering-Ziel zu füllen. mit speziellen Verzerrungs-Sprites (Beispiel unten).
Jede Farbkomponente im Verzerrungsziel (und in den Verzerrungssprites) repräsentiert Folgendes:
- R : dx: X-Offset - f (x) = 2x-1-Zuordnung ([0.0f, 1.0f] zu [-1.0f, 1.0f]).
- G : dy: Y-Offset - f (x) = 2x-1-Abbildung.
- B : m: Z Stärke - f (x) = x Abbildung.
Ein gutes Beispiel für ein Sprite, das für eine Welligkeit verwendet werden würde, wäre:
Das Ermitteln des Ergebnisses einer Welligkeit ist so einfach wie das Addieren der Wellen (unter Berücksichtigung der Zuordnung, die Sie zuerst auf [-1.0f, 1.0f] durchführen müssen); Da Wellen in der Realität auch additiv sind, funktioniert dies einfach - Sie erhalten sehr gute Annäherungen an reale Wellen.
Sobald Sie die beiden Renderziele haben, können Sie den folgenden Shader verwenden:
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();
}
}
Dies ist der endgültige Effekt:
Diese Technik sollte auch für 3D-Spiele funktionieren. obwohl Sie möglicherweise mehr über den Partikel-Shader und den Verzerrungs-Shader nachdenken müssen.