Jak połączyć kręgi wyboru jednostek?

16

Chciałbym wiedzieć, jak zrobić ten efekt wyboru scalonego okręgu. Oto zdjęcia do zilustrowania:

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

Zasadniczo szukam tego efektu:

wprowadź opis zdjęcia tutaj

Jak można uzyskać efekt scalenia kręgów? Nie znalazłem żadnego wyjaśnienia tego efektu. Wiem, że aby wyświetlić te tekstury, mogę opracować system kalkomanii, ale nie wiem, jak stworzyć efekt łączenia.

Jeśli to możliwe, szukam rozwiązania czysto shaderów.

Mata
źródło
Czy możesz wyjaśnić, co rozumiesz przez „efekt scalania”?
wondra
Oczywiście, jeśli spojrzysz na prawe górne znaki zrzutu ekranu, kalkomanie nie krzyżują się, ale dwa po lewej przecinają niebieskie koło i są scalane. Dodałem nowy zrzut ekranu, aby pokazać efekt.
MaT
Czy nalegasz na rozwiązanie cieniujące? Jeśli nie, właśnie rozwiązałeś to na swoim ostatnim zdjęciu.
wondra,
Ostatni zrzut ekranu pokazuje tylko efekt, na który celuję. Ostateczny wynik powinien wyglądać jak poprzednie zrzuty ekranu.
MaT
1
Tak, zgadzam się, myślę, że dynamicznie budują koło siatki z teksturą, a następnie przecinają siatkę, aby je scalić. Jest to również dobre rozwiązanie, ale myślę, że można go bardziej ograniczyć pod względem efektu.
MaT

Odpowiedzi:

8

Istnieje kilka sztuczek, które możesz zrobić:

Bufor Z.

Po renderowaniu wszystkich innych obiektów, dla każdej jednostki renderuj przezroczysty okrąg o mniejszym rozmiarze z maksymalną wartością Z. Następnie renderuj na ziemi naklejki z okręgami wyboru. Ponieważ znajdują się poniżej w kolejności Z, zostaną odrzucone, gdy znajdują się poniżej jednostek.

Bycie w pełni przezroczystym oznacza, że ​​okrąg jest zapisywany tylko do bufora Z (maksymalna wartość Z). Teraz, gdy renderujesz kalkomanie, są one testowane pod kątem wartości bufora Z, a jeśli pomyślnie przejdą test, są renderowane (co dzieje się tylko poza kręgami)

Szablon

Tak samo jak w poprzednim podejściu, ale tym razem użyj bufora szablonów. Renderuj mniejsze koła dla jednostek z pewną wartością szablonu, a następnie renderuj naklejki wyboru. Skonfiguruj szablon, aby odrzucić wszystkie elementy o wartości szablonu.

Kromster mówi, że popiera Monikę
źródło
Technika buforowania Z jest interesująca, ale nie rozumiem, w jaki sposób pierwszy przezroczysty okrąg może przyciąć naklejki naziemne.
MaT
0

Możesz na przykład sprawdzić w module cieniującym piksele renderujące, czy istnieje przecięcie z innymi naklejkami i zabić piksel, jeśli tak jest. Jest to dość skuteczne w przypadku tego rodzaju okrągłych naklejek.

JarkkoL
źródło
1
Zakładam, że pominąłeś część swojej odpowiedzi - aby przekazać wszystkie lokalizacje okręgów i promienie do modułu cieniującego.
Kromster mówi o wsparciu Moniki
@Krom Jeśli OP wyrazi jakiekolwiek zainteresowanie rozwiązaniem, chętnie podam więcej szczegółów.
JarkkoL,
0

Masz na myśli te niebieskie kółka na ziemi?

Może to być mądrzejszy sposób, aby to zrobić, ale rozważ moje rozwiązanie jako przykład, jak można to zrobić. Renderuj kręgi do osobnej pustej tekstury wielkości ekranu. W tym momencie możesz je ze sobą łączyć, jak chcesz. W zależności od potrzeb możesz napisać pełny kolor lub po prostu informację, że koło ma dany piksel. Jednak zdecydowanie potrzebujesz informacji o głębokości dla każdego zapisanego piksela, jeśli chcesz uzyskać efekt testu Z.

Podczas renderowania terenu po poprzednim kroku możesz próbkować utworzoną wcześniej teksturę, używając współrzędnych ekranu w module cieniującym piksele, jako UV. Teraz już wiesz, że okrąg powinien lub nie powinien być rzutowany na dany piksel terenu. Jednak w ten sposób będzie działać, jakby test Z był wyłączony, więc teren nie może ukryć żadnego koła. Jeśli chcesz, aby teren ukrywał koła znajdujące się za nim, wykonaj test głębokości przed zmieszaniem koła z teksturą terenu. Możesz użyć małego odchylenia, aby umożliwić renderowanie okręgów, które są nieco pod powierzchnią terenu, ale nadal chcesz je renderować.


Edycja: Teraz, aby uzyskać efekt scalonych kręgów, musisz: Podczas renderowania do osobnej tekstury musisz sprawdzić, czy istnieje już renderowany okrąg, w którym próbujesz wyrenderować nowy. (Sprawdź, czy tekstura ma tam wartość), jeśli tak, usuń ten piksel. Powinno to dać efekt „konturu”, gdy dwa lub więcej kół nakładają się na siebie. Aby działało to poprawnie, należy wykonać ten test tylko dla wnętrza koła, a nie granicy. Podczas renderowania okręgów zapisz określoną wartość do tekstury wyjściowej, która wskazuje, że jest to koło wewnątrz. Więc po prostu nie musisz renderować niczego na okręgu wewnątrz i powinieneś być dobry.

Edycja2: Dla Twojego prostego przykładu czerwony / zielony: Przed renderowaniem dowolnego piksela sprawdź, czy ten piksel nie jest już zielony. Jeśli tak, nie renderuj. To załatwi sprawę. W rzeczywistości, pisząc do tekstury, możesz nawet użyć czerwonego / zielonego na zewnątrz / wewnątrz koła, a następnie podczas renderowania terenu odczytaj te wartości i przekonwertuj je na pożądany kolor.

Jeśli przypadkiem moja odpowiedź jest zbyt abstrakcyjna, daj mi znać.

Elvithari
źródło
Rozumiem ogólny pomysł, ale jak mówisz, jest to dla mnie trochę abstrakcyjne dotyczące połączonych kręgów :)
MaT
0

Istnieje kilka opcji. Jako ogólna metoda, bufory szablonów często przydają się w miejscach, w których konieczne jest maskowanie niektórych rysunków, takich jak kontur, w którym koła pokrywają się w twoim przykładzie.

W tym przypadku myślę, że można to zrobić równie łatwo bez bufora szablonów. Możesz użyć bufora głębokości, aby wyeliminować kontur, w którym koła się nakładają. Chodzi o to, że narysujesz wnętrze kręgów tylko w buforze głębokości (ponieważ nie chcemy widzieć wnętrza), a następnie narysujesz kontur. W ten sposób część konturu pokrywająca się z innym okręgiem zostanie wyeliminowana przez test głębokości.

Jedynym zastrzeżeniem jest to, że musisz uważać na głębokość walki. Możesz użyć małego przesunięcia, aby upewnić się, że kontury faktycznie znajdują się za wnętrzem i zostać wyeliminowanym przez test głębokości. Alternatywą byłoby użycie glPolygonOffset().

Powiedzmy, że masz dwa okręgi, które są równoległe do płaszczyzny xy, ze środkami w (x1, y1, z) i (x2, y2, z). I masz te funkcje rysowania:

// Draw interior part of circle, shown in green in the schematic in the question.
drawInterior(x, y, z);

// Draw outline of circle, shown in red in the schematic in the question.
drawOutline(x, y, z);

Sekwencja rysowania wygląda wtedy tak, z deltaniewielkim przesunięciem:

glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
drawInterior(x1, y1, z + delta);
drawInterior(x2, y2, z + delta);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
drawOutline(x1, y1, z);
drawOutline(x2, y2, z);

źródło
0

Jeśli te kalkomanie są narysowane jako dyski, z czubka mojej głowy przetestowałbym każde koło pod kątem przecięcia ze sobą i umieściłem punkty przecięcia w tablicy. Następnie narysuj łuki, które nie znajdują się w przecięciu. Nie jest to jednak rozwiązanie cieniujące.

melfar
źródło
Tak, też o tym myślałem :) ale jak powiedziałeś, nie jest to rozwiązanie cieniujące i nie jest to bardzo ogólne rozwiązanie. Ale dzięki !
MaT
To dość niejasny opis
Kromster mówi, że popiera Monikę
0

Chcesz się wzorować tutaj. Twoje pierwsze przejście renderuje koła w buforze szablonu. Drugi przebieg renderuje widoczny kontur , wszędzie tam, gdzie bufor szablonów się nie zmienił. Drugie przejście musi wykorzystywać geometrię większą niż pierwsze przejście, w tym przypadku wystarczy prosty skalar liniowy.

Chociaż rozwiązanie, które mam tutaj do rysowania konturów , jest więcej niż potrzebujesz (ponieważ ten moduł cieniujący zamienia każdą krawędź siatki w pełny quad), stosuje się to podejście: rysowanie oryginalnego modelu w buforze szablonów, a następnie renderowanie większej wersji, w której bufor szablonu nadal wynosi 0.

Draco18s nie ufa już SE
źródło
Dzięki! Zamiast więc najpierw narysować widoczne części, powinienem zacząć od renderowania przezroczystych kół w szablonie. Ale jak renderować okrągłe przezroczyste koła? Nie mogę ograniczyć części obrazu do renderowania w szablonie. Kiedy renderuję na szablonie, wszystko tam idzie, prawda?
Doodlemeat
Tak, dlatego drugie przejście (część widoczna) jest skalowane w większym stopniu: więc jego granice są większe niż bufor szablonu. Musisz tylko zastosować skalar wierzchołka w drugim przejściu (rozejrzyj się za shaderem konturu, większość z nich używa prostszego skalaru, o którym mówię). Nie można również zmienić buforu szablonu, jeśli kolor jest przezroczysty. W tym przypadku prawdopodobnie będziesz potrzebować drugiej maski teksturowej lub możesz wykonać matematykę odległości, aby określić okrąg. Potrzebuję kilku godzin i dostępu do Unity, aby podać dowolny kod.
Draco18s nie ufa już
Hmm, co powiesz na posiadanie czarno-białego obrazu tylko do zapisu w buforze szablonów w pierwszym przejściu, tak że czarny staje się 0, a biały staje się 1 w szablonie. Czy to w ogóle jest możliwe?
Doodlemeat
To właśnie miałem na myśli przez drugą maskę tekstur. Jestem prawie pewien, że to zadziała, po prostu nie mogę zweryfikować bez Unity przede mną, którego nie będę miał przez ponad 24 godziny.
Draco18s nie ufa już