Sprites de contour

9

Je travaille actuellement sur un jeu 2D, et ma tâche actuelle est de définir l'objet sélectionné.

J'utilise essentiellement un shader de flou pour le faire entièrement en runtime. Je dessine d'abord mon sprite à l'aide d'un shader de flou gaussien vertical, puis je le dessine avec un shader de flou gaussien horizontal, puis je dessine mon sprite normalement.

Voici mon shader de flou: sampler TextureSampler: register (s0);

#define SAMPLE_COUNT 15

float2 SampleOffsets[SAMPLE_COUNT];
float SampleWeights[SAMPLE_COUNT];


float4 PixelShaderFunction(float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 c = 0;

    // Combine a number of weighted image filter taps.
    for (int i = 0; i < SAMPLE_COUNT; i++)
    {
        c += tex2D(TextureSampler, texCoord + SampleOffsets[i]) * SampleWeights[i];
    }

    return c;
}

SampleOffets sont les décalages me permettant de tester les pixels d'arrondi. Les SampleWeights sont des poids calculés avec la fonction gaussienne ( http://en.wikipedia.org/wiki/Gaussian_blur )

Voici le résultat:

entrez la description de l'image ici

Ce n'est pas si mal, assez lisse, mais pas assez visible dans le jeu ... Mais j'aimerais pouvoir contrôler l'épaisseur (pour l'agrandir), et ajouter un premier contour opaque avant de le fondre en alpha (pour faire plus visible). Et j'ai l'impression que le flou gaussien n'est peut-être pas aussi bon que je le pensais pour ma tâche :)

Une autre idée est de le générer automatiquement à partir du .png (en utilisant un script photoshop pour le rendre automatique). J'ai juste besoin de remplir les pixels du contour avec une couleur personnalisée, en stockant la valeur alpha dans le composant rouge par exemple, et de mettre tous les autres composants à 0. Ensuite, je n'ai qu'à appliquer un shader qui remplace les pixels transparents à la couleur que je veux

float4 PixelShaderFunction2(float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 color = tex2D(TextureSampler, texCoord);
    float4 newColor = 0;
    if (color.a == 0 && color.r != 0)
    {
        color.a = color.r;
        // Blue outline
        color.b = 1;
    }
}

Le problème est que j'utilise la compression DXT5 pour mon sprite, donc je ne peux pas être sûr que la couleur que j'obtiendrai dans mon shader sera exactement la même que celle que j'ai écrite. C'est pourquoi je ne l'ai même pas essayé ... Des pensées?

Tout conseil serait le bienvenu :)

s0ubap
la source
Vous devez être en mesure de contrôler l'épaisseur et la chute alpha dans votre shader. Voulez-vous l'afficher pour référence?
Seth Battin
J'ai utilisé le shader de flou gaussien de cet échantillon: lien permettez-moi de modifier mon article pour vous montrer le shader en détail
s0ubap
Je ne suis pas sûr que le flou gaussien soit le bon pour vous. Essayez plutôt un flou radial.
user1306322

Réponses:

6

Ce que vous recherchez probablement, c'est une forme de détection des contours avant, après ou même avant et après votre flou gaussien. Peut-être qu'une version de Sobel Edge Detection pourrait fonctionner. Je sais que votre jeu est en 2D mais si la page wiki est trop grossière, voici un tutoriel sur la façon de le faire fonctionner dans l'UDK qui pourrait mieux se traduire.

Votre détection de bord n'a vraiment besoin de trouver les bords du canal alpha que si vous avez besoin d'un boost de vitesse.

Alex Shepard
la source
Intéressant! Je l'ai essayé. Le résultat était bon, sauf quand je fais un zoom avant / arrière ... Les pixels apparaissent et disparaissent, entraînant des artefacts indésirables ...
s0ubap
1
Quel genre d'artefact voyez-vous? Pouvez-vous fournir une image?
Alex Shepard
2

Ce qui a fonctionné pour moi avec le texte décrivant était:

  • Choisissez la couleur du contour
  • Dessinez le texte en (x-1, y-1) avec la couleur de contour
  • Dessinez le texte en (x + 1, y-1) avec la couleur de contour
  • Dessinez le texte en (x-1, y + 1) avec la couleur de contour
  • Dessinez le texte en (x + 1, y + 1) avec la couleur de contour
  • Dessinez le texte en (x, y)

Vous pouvez faire la même chose - tout ce que vous avez à faire est de dessiner le sprite avec les pixels opaques colorés avec votre couleur de contour. (Conservez les valeurs de transparence pour que les bords arrondis soient toujours ronds).

Cela fonctionne mieux que de dessiner une version à l'échelle et possède d'autres propriétés intéressantes (comme pouvoir contrôler l'alpha du contour pour l'audace et conserver tous les "trous" dans votre image de sprite) - le seul inconvénient est que vous pouvez ' t vraiment trop contrôler la largeur du contour.

cendres999
la source
1

Je suis un peu nouveau pour tout cela, mais voici mon idée:

Vous pouvez utiliser le canal alpha de votre texture pour créer une autre texture. Toute valeur alpha inférieure à une valeur seuil sera définie comme entièrement transparente. Tout ce qui précède sera entièrement opaque. En utilisant cette nouvelle texture, vous pouvez définir les valeurs de RVB pour être de n'importe quelle couleur que vous souhaitez. Mettez à l'échelle cette nouvelle "texture" pour qu'elle soit légèrement plus grande que la texture de votre personnage. Cela vous donnerait une belle couleur unie autour du personnage. Ensuite, utilisez cette couleur avec votre shader gaussien pour donner la belle lueur décrite autour de votre texture créée. Je suppose que cela pourrait être fait sans créer une autre texture, et être tout shader basé sur la texture du personnage.

Est-ce que cela a du sens?

aglassman
la source
Cette méthode présente un défaut majeur lorsqu'il s'agit de formes non concaves. Par exemple, lorsqu'il est appliqué à un beignet, seul le bord extérieur aura un contour. Sans parler des autres distorsions d'épaisseur du contour.
Kromster