Contorni di sprite


9

Attualmente sto lavorando a un gioco 2D e il mio compito attuale è delineare l'oggetto selezionato.

Fondamentalmente uso uno shader di sfocatura per farlo completamente in fase di esecuzione. Prima disegno il mio sprite usando uno shader di sfocatura gaussiana verticale, quindi lo disegno con uno shader di sfocatura gaussiana orizzontale, e quindi disegno il mio sprite normalmente.

Ecco il mio blur shader: 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 sono gli offset che mi consentono di testare i pixel di arrotondamento SampleWeights sono pesi calcolati con la funzione gaussiana ( http://en.wikipedia.org/wiki/Gaussian_blur )

Ecco il risultato:

inserisci qui la descrizione dell'immagine

Non è così male, abbastanza liscio, ma non abbastanza visibile nel gioco ... Ma mi piacerebbe essere in grado di controllare lo spessore (per ingrandirlo) e aggiungere un primo contorno opaco prima di sbiadirlo in alpha (per rendere più visibile). E sento che la sfocatura gaussiana non è forse così buona come pensavo per il mio compito :)

Un'altra idea è di generarlo automaticamente dal .png (usando uno script di Photoshop per renderlo automatico). Devo solo riempire i pixel di contorno con un colore personalizzato, archiviando ad esempio il valore alfa nel componente Rosso e impostare tutti gli altri componenti su 0. Quindi devo solo applicare uno shader che sostituisce i pixel trasparenti con il colore che desidero

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;
    }
}

Il problema è che sto usando la compressione DXT5 per il mio sprite, quindi non posso essere sicuro che il colore che otterrò nel mio shader sarà esattamente lo stesso che ho scritto. Ecco perché non l'ho nemmeno provato ... Qualche idea?

Qualsiasi consiglio sarebbe il benvenuto :)


Dovresti essere in grado di controllare lo spessore e la caduta di alfa nel tuo shader. Ti va di pubblicarlo come riferimento?
Seth Battin

Ho usato lo shader di sfocatura gaussiana da questo esempio: link fammi modificare il mio post per mostrarti lo shader in dettaglio
s0ubap

Non sono sicuro che la sfocatura gaussiana sia quella giusta per te. Prova invece un po 'di sfocatura radiale.
user1306322

Risposte:


6

Ciò che probabilmente stai cercando è una forma di rilevamento dei bordi prima, dopo o anche prima e dopo la sfocatura gaussiana. Forse una versione di Sobel Edge Detection potrebbe funzionare. So che il tuo gioco è in 2D ma se la pagina della wiki è troppo approssimativa ecco un tutorial su come farlo funzionare nell'UDK che potrebbe tradursi meglio.

Il tuo rilevamento dei bordi deve davvero trovare i bordi del canale alfa se hai bisogno di un aumento di velocità.


Interessante! L'ho provato. Il risultato è stato buono, tranne quando ingrandisco / rimpicciolisco ... I pixel appaiono e scompaiono, causando artefatti indesiderati ...
s0ubap

1
Che tipo di artefatto stai vedendo? Puoi fornire un'immagine?
Alex Shepard

2

Ciò che ha funzionato per me con la descrizione del testo è stato:

  • Scegli il colore del contorno
  • Disegna il testo in (x-1, y-1) con il colore del contorno
  • Disegna il testo in (x + 1, y-1) con il colore del contorno
  • Disegna il testo in (x-1, y + 1) con il colore del contorno
  • Disegna il testo in (x + 1, y + 1) con il colore del contorno
  • Disegna il testo in (x, y)

Puoi fare la stessa cosa: tutto ciò che devi fare è disegnare lo sprite con i pixel opachi colorati con il colore del contorno. (Mantenere i valori di trasparenza in modo che i bordi arrotondati continuino a essere circolari).

Funziona, sembra meglio che disegnare una versione ridimensionata e ha alcune altre proprietà interessanti (come essere in grado di controllare l'alfa del contorno per audacia e mantenere eventuali "buchi" nell'immagine sprite) - l'unico inconveniente è che puoi ' controlla davvero troppo bene la larghezza del contorno.


1

Sono un po 'nuovo di tutto questo, ma ecco la mia idea:

È possibile utilizzare il canale alfa della trama per creare un'altra trama. Qualsiasi valore alfa inferiore a un valore di soglia verrà impostato su completamente trasparente. Quanto sopra sarà completamente opaco. Usando questa nuova trama, puoi impostare i valori di RGB su qualsiasi colore desideri. Scala questa nuova "trama" in modo che sia leggermente più grande della trama del tuo personaggio. Questo ti darebbe un bel colore solido attorno al personaggio. Quindi usa quel colore con il tuo shader gaussiano per dare il piacevole bagliore delineato intorno alla texture creata. Immagino che questo possa essere fatto senza creare un'altra trama ed essere tutto shader basato sulla trama del personaggio.

Ha senso per niente?


Questo metodo ha un grosso difetto quando si tratta di forme non concave. Ad esempio, quando applicato a una ciambella, solo il bordo esterno otterrà un contorno. Per non parlare di altre distorsioni dello spessore del contorno.
Kromster
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.