Zarys sprites

9

Obecnie pracuję nad grą 2D, a moim bieżącym zadaniem jest obrysowanie wybranego obiektu.

Zasadniczo używam modułu cieniującego rozmycie, aby zrobić to w pełni. Najpierw rysuję duszka za pomocą pionowego gaussowskiego shadera rozmycia, następnie rysuję go poziomym gaussowskim shaderem rozmycia, a następnie rysuję duszka normalnie.

Oto mój shader shadera: 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 to przesunięcia pozwalające mi testować zaokrąglanie pikseli. SampleWeights to wagi obliczane za pomocą funkcji gaussa ( http://en.wikipedia.org/wiki/Gaussian_blur )

Oto wynik:

wprowadź opis zdjęcia tutaj

To nie jest takie złe, dość gładkie, ale niewystarczająco widoczne w grze ... Ale chciałbym móc kontrolować grubość (aby ją powiększyć) i dodać pierwszy nieprzezroczysty kontur przed zaniknięciem go w alfa (aby zrobić to bardziej widoczne). I czuję, że rozmycie gaussowskie może nie jest tak dobre, jak myślałem dla mojego zadania :)

Innym pomysłem jest wygenerowanie go automatycznie z .png (za pomocą skryptu photoshopa, aby był automatyczny). Muszę tylko wypełnić piksele konturu niestandardowym kolorem, przechowując na przykład wartość alfa w składniku Czerwonym i ustawić wszystkie pozostałe komponenty na 0. Następnie muszę zastosować moduł cieniujący, który zastępuje przezroczyste piksele wybranym kolorem

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

Problem w tym, że używam kompresji DXT5 dla mojego duszka, więc nie mogę być pewien, że kolor, który otrzymam w moim module cieniującym będzie dokładnie taki sam, jak napisałem. Dlatego nawet tego nie spróbowałem ... Jakieś myśli?

Wszelkie porady będą mile widziane :)

s0ubap
źródło
Powinieneś być w stanie kontrolować grubość i odchylenie alfa w shaderze. Chcesz opublikować go w celach informacyjnych?
Seth Battin
Użyłem gaussowskiego modułu cieniującego rozmycie z tej próbki: link pozwala mi edytować mój post, aby pokazać Ci szczegółowo moduł cieniujący
s0ubap
Nie jestem pewien, czy rozmycie gaussowskie jest dla Ciebie odpowiednie. Zamiast tego spróbuj rozmycia promieniowego.
user1306322

Odpowiedzi:

6

Prawdopodobnie szukasz formy wykrywania krawędzi przed, po, a nawet przed i po rozmyciu gaussowskim. Może wersja Sobel Edge Detection mogłaby działać. Wiem, że twoja gra jest 2D, ale jeśli strona wiki jest zbyt szorstka, oto samouczek, jak ją uruchomić w UDK, która może się lepiej tłumaczyć.

Twoje wykrywanie krawędzi naprawdę musi znaleźć krawędzie kanału alfa, jeśli potrzebujesz przyspieszenia.

Alex Shepard
źródło
Ciekawy! Próbowałem tego. Wynik był dobry, z wyjątkiem sytuacji, gdy powiększam / pomniejszam ... Piksele pojawiają się i znikają, powodując niechciane artefakty ...
s0ubap
1
Jakiego rodzaju artefakt widzisz? Czy możesz podać obraz?
Alex Shepard
2

To, co zadziałało dla mnie przy opisie tekstu, to:

  • Wybierz kolor konturu
  • Narysuj tekst w (x-1, y-1) kolorem konturu
  • Narysuj tekst w (x + 1, y-1) za pomocą koloru konturu
  • Narysuj tekst w (x-1, y + 1) za pomocą koloru konturu
  • Narysuj tekst w (x + 1, y + 1) za pomocą koloru konturu
  • Narysuj tekst w (x, y)

Możesz zrobić to samo - wszystko, co musisz zrobić, to narysować duszka nieprzezroczystymi pikselami pokolorowanymi konturem. (Zachowaj wartości przezroczystości, aby okrągłe krawędzie nadal wyglądały na okrągłe).

Działa to, wygląda lepiej niż rysowanie wersji skalowanej i ma kilka innych fajnych właściwości (takich jak możliwość kontrolowania zarysu alfa pod kątem pogrubienia i zachowanie wszelkich „dziur” w obrazie duszka) - jedyną wadą jest to, że możesz „ Naprawdę zbyt dobrze kontrolujesz szerokość konturu.

ashes999
źródło
1

Jestem trochę nowy w tym wszystkim, ale oto mój pomysł:

Możesz użyć kanału alfa tekstury, aby utworzyć inną teksturę. Każda wartość alfa poniżej wartości progowej zostanie ustawiona na w pełni przezroczystą. Wszelkie powyższe będą całkowicie nieprzejrzyste. Korzystając z tej nowej tekstury, możesz ustawić wartości RGB na dowolny kolor, jaki chcesz. Skaluj tę nową „teksturę”, aby była nieco większa niż tekstura postaci. To da ci ładny jednolity kolor wokół postaci. Następnie użyj tego koloru za pomocą shadera Gaussa, aby nadać przyjemny kontur wokół stworzonej tekstury. Domyślam się, że można to zrobić bez tworzenia kolejnej tekstury, i wszystko opierać się na cieniowaniu opartym na teksturze postaci.

Czy to w ogóle ma sens?

aglassman
źródło
Ta metoda ma poważną wadę w przypadku kształtów nie wklęsłych. Np. Po nałożeniu na pączek tylko zewnętrzna krawędź otrzyma kontur. Nie wspominając o innych zniekształceniach grubości konturu.
Kromster