Jak mogę proceduralnie renderować paski zdrowia o nieregularnym kształcie?

35

Problem tradycyjnego prostokątnego paska zdrowia opartego na sercu jest czymś dobrze zrozumiałym i łatwym do rozwiązania. Ale jakie jest zaakceptowane rozwiązanie dla bardziej „kreatywnych” pasków zdrowia, takich jak makieta, którą wykonałem poniżej?

Puste zdrowie Pełne zdrowie, częściowe zdrowie

Oczywistym sposobem na to byłoby mieć duszki „pomiędzy”, więc trzeci obraz byłby własnym duchem, wraz z wieloma innymi przejściami dla różnych poziomów zdrowia. Wydaje się to jednak nieeleganckie, a liczba osób w wieku dojrzałym potrzebnych do płynnego przejścia między stanami zdrowia byłaby duża.

Jedynym innym pomysłem, jaki mogę wymyślić, jest nałożenie duszka „pełnego zdrowia” na duszka „pustego zdrowia” i wstępne upieczenie zestawów współrzędnych pikseli, które reprezentują każdy tik zdrowia, a następnie uczynienie ich nieprzezroczystymi lub przezroczystymi jako zdrowie idzie w górę lub w dół.

Mam nadzieję, że to pytanie będzie niezależne od języka i platformy, ale mogę podać konkretną próbkę w dowolnym języku / bibliotece / środowisku, jeśli pomoże to w uzyskaniu odpowiedzi.

msd7734
źródło
5
„N̶a̶n̶o̶m̶a̶c̶h̶i̶n̶e̶s̶ Shaders, syn”
Mukesh Ingham
Wydaje mi się, że to przejście można zdefiniować matematycznie. Stamtąd komputer może obliczyć współrzędne pikseli, aby je pokazać / ukryć, zamiast je wstępnie przygotowywać
Richard Tingle
W jaki sposób pasek zdrowia w kształcie serca jest „łatwy do rozwiązania”?
MooseBoys
1
@MooseBoys Mówiłem o zdrowiu opartym na sercu, a nie w kształcie serca. Pomyśl o grach Legend of Zelda. Przepraszam, że nie jestem bardziej klarowny.
msd7734
@RichardTingle, dobry pomysł :)
Jon

Odpowiedzi:

48

Jest to bardzo prosty sposób osiągnięcia tego za pomocą shaderów, potrzebujesz trzech * tekstur: pusty pasek zdrowia, tekstura paska zdrowia i maska ​​z gradientem rozkładu zdrowia z jednym skrajnym (np. Najciemniejsza, nie czarna lub najbardziej przezroczysta wartość alfa) na jednym końcu i inne na drugim końcu. Najlepiej widać to na obrazie, obecnie nie jestem w stanie narysować zakrzywionego gradientu tylko liniowego - ale jestem pewien, że twoi artyści nie będą mieli żadnych problemów: wprowadź opis zdjęcia tutaj teraz w próbce cieniowania zarówno tekstury, jak i próg wartości maski, odrzucają wszystkie piksele, które nie są jaśniejszy niż próg wejściowy (na podstawie wejściowego% shadera zdrowia).
Państwo mogliużyj maski matematycznej do maskowania zamiast tekstury, ale jeśli to zrobisz, nadal będziesz bardzo ograniczony do kształtów, które jesteś w stanie (= proste) stworzyć za pomocą tych formuł - a znalezienie jednego nie jest trywialne.
* patrz komentarze

wondra
źródło
9
W wielu przypadkach (w tym przykład PO) użycie oddzielnej tekstury dla koloru jest przesadą. W większości przypadków można po prostu odwzorować gradient maski w skali szarości na kolory określone jako jednolite dla modułu cieniującego, jednocześnie odrzucając wartości maski poniżej określonego progu.
bcrist
1
Tak naprawdę nie potrzebujesz najciemniejszego, a nie czarnego, możesz użyć kanału alfa, aby odfiltrować niepotrzebne piksele.
Jack Aidley
1
@JackAidley na pewno byłoby to możliwe, ale chciałem, aby to rozwiązanie było jak najbardziej elastyczne - w większości tytułów AAA nie masz HP tylko „czerwonego”, ale jest teksturowane.
wondra
1
@ bcrist dobry punkt, rozważałem zasugerowanie go jako optymalizacji. Ale nie mogłem go poprawnie narysować, więc postanowiłem, aby był tak prosty, jak to możliwe i pozostawić optymalizację do wdrożenia.
wondra
@wondra W wielu przypadkach, w tym przykładowy wygląd w PO, można użyć gradientu proceduralnego lub jednowymiarowego wyszukiwania kolorów (z poziomem maski jako wejściem) zamiast tekstury.
Random832
34

Zaimplementowane matematycznie, jako moduł cieniujący piksele:

Na CPU obliczyć HealthDirection i jego iloczyn iloczynu za pomocą V2 wprowadź opis zdjęcia tutaj

Na GPU obliczyć znormalizowany kierunek od punktu środkowego dla każdego piksela. Porównaj każdy produkt kropkowy z HealthDirections ', aby wybrać, czy odcień „tła”, czy kolor. wprowadź opis zdjęcia tutaj

Jeśli „odwróciłeś” ten algorytm i działałeś w innym kierunku, możesz „rozproszyć” kierunek każdego piksela z powrotem na wartość procentową i porównać je z innymi z HealthPercent. Po obliczeniu procentu każdego piksela, przechodzenie z zanikania z czerwonego na zielony na GPU staje się banalne.

Najpierw narysuj pasek, stosując algorytm do kwadratu; kolory wyjściowe między rangeMin i rangeMax (można upiec) i clip () lub wydruk przezroczysty w każdym innym miejscu. Następnie narysuj (zmodyfikowany) duszek nad nim, używając alfa. Śledziłem twój pasek w CAD, wypełniłem go zalaniem, a następnie „magicznie wędrowałem” jednolitym kolorem w programie Paint, aby go usunąć. Mój wygląda jak gówno z powodu ręcznego mieszania AutoCAD i Paint; zakładając, że połączysz wewnętrzne krawędzie z przezroczystymi, twoje będą wyglądać idealnie .

Biała ramka to granice quada. To i czerwone X są tylko w celach informacyjnych:

wprowadź opis zdjęcia tutaj

„Duszek z dziurą” nie musi być renderowany w tym samym czasie co pasek zdrowia. Powinny otrzymać instancję i wylosować wszystkie naraz, po zakończeniu wszystkich pasków zdrowia. Ponieważ algorytm jest samowystarczalny w module cieniującym, możesz również dodać do niego instancję, a następnie narysować wszystkie paski zdrowia za pomocą jednego wywołania losowania. Narysowanie każdego paska zdrowia na ekranie powinno zająć 2 połączenia DrawInstanced (...) i być „szalonym szybkim”.

Jon
źródło
1
Jeśli zamierzasz maskować w taki sposób, możesz to zrobić bardziej efektywnie, po prostu zmieniając kreślone trójkąty dla okrągłego zanikania.
Jack Aidley
@JackAidley, proszę być bardziej szczegółowym, ponieważ nie uważam tego maskowania; pasek postępu jest w pełni renderowany na swoim miejscu tylko w dwóch trójkątach, bez próbkowania, po pierwszym przejściu. Duszek po prostu ma dziurę i „ładnie” wszystko na końcu. (To jest jakaś maska, ale nie jako integralna część algorytmu?) Dzięki
Jon
To, co robisz, jest równoważne narysowaniu zamaskowanej wersji w kolorze kolorowego paska na ikonce tła, która ma już szary kolor na swoim miejscu. Ponieważ twoja metoda wymaga niestandardowego modułu cieniującego i zapisuje na każdym pikselu metodę wolniejszą niż rysowanie tylko pożądanej części kształtu.
Jack Aidley
@JackAidley, ale nie ma duszka w tle? Tęcza jest rysowana przy użyciu tylko czterech pozycji świata float3; bez promieni UV, bez „duszka w tle”. Martwisz się również, że moduł cieniujący pikseli ugrzęźnie podczas pracy na niewielkich quadach? Ponadto RangeMin i RangeMax clip () większość tych fragmentów, natychmiast.
Jon
Będziesz potrzebował ikonki tła, aby uzyskać obramowania, jak pokazano na oryginalnym obrazie; jeśli je pominiesz, to tak, metody są różne.
Jack Aidley