Effet de vague ondulée?

9

Je travaille sur un jeu de tower defense depuis un certain temps maintenant, et jusqu'à présent, je suis vraiment satisfait des résultats. Cependant, il y a une chose que j'aimerais ajouter.

J'ai vu une vidéo de GeoDefense pour Windows Phone 7 ici: http://www.youtube.com/watch?v=YhPr4A4LRPQ

Remarquez comment (quand une unité est tuée ou qu'un projectile frappe une unité), l'arrière-plan ondule dans une sorte d'effet de vague.

Comment puis-je faire un équivalent? Je pense que je dois en quelque sorte le faire dans le vertex shader, avec un quadruple composé de nombreux sommets.

Quel est ton appel?

Modifier Il est important de noter que mon jeu XNA n'est pas conçu pour Windows Phone, mais pour les PC Windows.

Mathias Lykkegaard Lorenzen
la source

Réponses:

8

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:

Ripple Sprite

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:

Effet d'entraînement

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.

Jonathan Dickinson
la source
Je ne crée pas le jeu pour Windows Phone. J'ai mis à jour ma question.
Mathias Lykkegaard Lorenzen
@MathiasLykkegaardLorenzen J'ai retiré du contenu de mon blog et l'ai mis dans la réponse, j'espère que cela vous donne un bon point de départ.
Jonathan Dickinson
L'exemple du téléphone est sympa et c'est exactement ce que j'essaie de faire. Malheureusement, je veux que l'effet bouge avec le monde et ne soit pas basé sur les coordonnées de l'écran. Est-ce possible?
Mathias Lykkegaard Lorenzen
@MathiasLykkegaardLorenzen C'est certainement possible, mais ce sera incroyablement cher - dans ce cas, je vous recommande d'opter pour ma solution. Je vous enverrai le code si je peux le trouver; tant que vous vous engagez à ne pas utiliser mes œuvres d'art :).
Jonathan Dickinson
@Jonathan Dickinson Pouvez-vous nous fournir le code XNA 4 mis à jour?
Amir Rezaei