Najlepszy sposób, aby pozwolić graczom „Barwić” obrazy bez utraty jakości kolorów?

41

Tworzę grę izometryczną 2.5D (obrazy 2D).

Chcę, aby gracze mogli „farbować” swoją zbroję, ubrania i inne rzeczy. Uważam, że wszystko w skali szarości prowadzi do utraty niektórych bardziej „naturalnych” kolorów. Na przykład zrobienie smoka z czerwoną / żółtą skalą szarości, a następnie nałożenie koloru nakładki, prowadzi do czysto czerwonego smoka z utratą drugiego koloru. Tymczasem śmierć tego samego Czerwonego / Żółtego Smoka Niebieskiego sprawia, że ​​jest on Niebiesko-Biały, co wygląda świetnie.

Postacie w mojej grze nie mają ogromnej różnorodności wyposażenia. Gra jest bliżej sposobu, w jaki League of Legends obsługuje postacie i grafikę. Może istnieć jeden typ postaci (np. Bohater), ale wiele strojów dla postaci jako opcji. Chcę, aby gracze mieli jak najwięcej możliwości dostosowywania w ograniczonej liczbie „strojów” i postaci.

Chcę więc, aby gracze mogli wybrać postać, wybrać jedną z kilku broni, naprzemiennie między garścią kostiumów (ułożonych na postaciach), a następnie farbować większość wszystkiego (wybierz konkretny metaliczny kolor dla broni, wybierz dowolny kolor w ogóle na ubrania).

Gdybym miał możliwość używania skali szarości bez utraty koloru, zrobiłbym to.

Oto przykład tego, o czym mówię:

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

Nie jest nawet możliwe „farbowanie” smoka, bez względu na to, czego używam w opcjach „Color Overlay” programu Photoshop. Oczywiście robię to źle, jeśli można lepiej go pokolorować za pomocą skali szarości. W przypadku koloru takiego jak zielony lub żółty lub jaśniejszy fiolet działa to dobrze. W przypadku każdego innego koloru niszczy sztukę.

Wygląda jednak znacznie lepiej, jeśli NIE wykonuję go w skali szarości, a zamiast tego po prostu zastosuję kolor „HUE” na oryginalnym obrazie (czerwony / żółty).

Czerwony odcień wprowadź opis zdjęcia tutaj

Fioletowy odcień wprowadź opis zdjęcia tutaj

Teraz gracze mogą farbować DOWOLNY kolor, i nadal wyglądałby świetnie! (Żółty zmienia kolor na biały, a czerwony na dowolny kolor tęczy.)

Czy to oznacza, że ​​BIAŁY lub CZARNY jest najlepszym kolorem wtórnym? Następnie użyć jakiejś metody lub modułu cieniującego, aby zmienić biały (wtórny) kolor na coś innego?

Czy są jakieś artykuły na temat tej złożonej metody robienia pojedynczego zdjęcia, a na podstawie kolorystyki barwią różne piksele?

Czy w przypadku Smoka najlepiej sprawdziłby się jako smok o wysokim kontraście w kolorze białym / czarnym? Czy czerwony / żółty jest najlepszym zestawem kolorów? Okazuje się znacznie lepiej dla obrazów niż kilka innych kolorów, które wypróbowałem. Czy skala szarości jest nadal lepsza?

Czy „Opcje mieszania” programu Photoshop nie obejmują metody odpowiedniego „farbowania” obrazów w grze wideo? Czy istnieją złożone Shadery / metody, które pozwalają mi osiągnąć lepszy sukces?

Uwaga: Jeśli GrayScale pozwala mi zmniejszyć zużycie pamięci RAM przez moje obrazy lub zapobiec utracie jakości podczas stratnej kompresji, byłoby to coś, co poważnie rozważę.

Carter81
źródło
5
To jest uzasadnione. Głosuję za tym i mam nadzieję, że zwróci na to uwagę. Teoria kolorów to świetny temat.
Evan
Obracanie odcienia jest możliwe, choć w 2D - nie wiem, czy zadziałałoby w 3D.
ashes999
Dziękuję Evan. Zgadzam się również, że jest to niezwykle interesujące i jest to jeden z najlepszych tematów, które badałem w swoim czasie. Wyobrażam sobie, że ten rodzaj pracy rzadko jest wykonywany, ponieważ wymagałby artysty - ale nie tylko artysty - artysty zajmującego się teorią kolorów, programami cieniującymi gry wideo, a nawet koderem. Mogę sobie tylko wyobrazić, że znalezienie kogoś, kto wyróżnia się zarówno sztuką, jak i programowaniem, jest rzadkością. W Google nie ma prawie żadnych badań na ten temat. Zwłaszcza dla kogoś, kto nie ma pojęcia, jakie kluczowe warunki badań. Na pewno nie jestem artystą.
Carter81

Odpowiedzi:

19

Przesunięcie odcienia to jedna z możliwości, która pozwoli Ci uzyskać gamę kolorów bez utraty szczegółów kolorów. Podstawową ideą jest konwersja każdego piksela z przestrzeni RGB na przestrzeń HSV, następnie przesunięcie odcienia o wartość zdefiniowaną przez użytkownika, a następnie konwersja z powrotem do RGB. W rzeczywistości można to zrobić bardziej efektywnie, stosując macierz obrotu do wartości RGB: utwórz macierz, która obraca się wokół osi (1, 1, 1) o zdefiniowany przez użytkownika kąt odcienia. Następnie możesz po prostu zastosować tę macierz do każdej wartości RGB w module cieniującym piksele.

Pozwoli to na zmianę czerwono-żółtego smoka na żółto-zielonego, zielono-niebieskozielonego, niebieskozielonego, niebiesko-purpurowego lub purpurowo-czerwonego. Jest to nieco restrykcyjne, ponieważ przy takim podejściu nie można niezależnie zmienić dwóch kolorów. Zachowają swój względny odcień, gdy są autorstwa oryginalnego obrazu. Istnieje również kilka kolorów, do których nie masz dostępu, np. Nie możesz w ten sposób stworzyć czarno-białego smoka. Może to jednak wystarczyć do Twoich celów.

Inna możliwość, jeśli twoje modele mają dwa lub trzy „kolory podstawowe” (tutaj czerwony i żółty), możesz stworzyć oryginalny obraz, używając osobnego kanału kolorów dla każdego koloru kluczowego. W takim przypadku autor stworzyłby smoka czerwonego i zielonego zamiast czerwonego i żółtego, a gdybyś miał trzeci kolor, mógłbyś go napisać na niebiesko. Następnie możesz pozwolić użytkownikowi wybrać trzy kluczowe kolory i użyć czerwonych, zielonych i niebieskich wartości na obrazie jako ilości tych zdefiniowanych przez użytkownika kolorów, aby się wtopiły. Tak więc moduł cieniujący piksele wyglądałby jak

finalColor = image.r * userColor1 + image.g * userColor2 + image.b * userColor3;

Pozwoli to użytkownikom wybrać dowolną kombinację kolorów, w tym czarno-białą lub fioletową i złotą.

Nathan Reed
źródło
1
+1 za nie tylko dobrą odpowiedź, ale odpowiedź na rzadki temat (teoria kolorów). Nie mam pojęcia, dlaczego wcześniej o tym nie myślałem. RGB. Czerwony zielony niebieski. DUH! Najlepsze kolory do użycia to prawdopodobnie te dokładnie trzy kolory, ze względu na możliwość manipulowania poszczególnymi kanałami.
Carter81
1
Przesunięcie kolorów jest bardzo trudnym tematem, ponieważ większość informacji o obrazie jest przekazywana przez jasność, a proste przesunięcie odcienia nie zachowuje jasności. Różne odcienie mają różne wartości jasności. Potrzebujesz do tego bardziej zaawansowanych algorytmów.
API-Beast
10

Problem, przed którym stoisz, polega na tym, że nie możesz po prostu „odcień” całego obrazu, a wygląd, który widzisz, jest czymś więcej niż tylko kolorem podstawowym. Dla jednego masz drobne gradienty z jednego materiału na drugi, ale co ważniejsze, masz również odbicia, światła i cienie, na które nie ma wpływu kolor podstawowy. (Te są w zasadzie dodawane na górze.)

Musisz więc rozłożyć obraz na jego komponenty.

Przykład :

Zdekonstruowany obraz Barwione Przykłady

W tym przypadku mamy 3 warstwy:

  • Tło - zawiera elementy, których nie należy pokolorować.
  • Część, która powinna być pokolorowana - Mnoży się przez kolor. (OpenGL mnoży się domyślnie, jeśli podasz kolor inny niż biały).
  • Najważniejsze informacje - są one dodawane do całego obrazu. Nie jest biały, ale żółty, aby naśladować zmianę odcienia. Obiekty nie są tylko jednym kolorem, odcień zmienia się wraz z jasnością.
API-Beast
źródło
+1. Ale „nie można po prostu„ odcień ”całego obrazu” jest nieco mylące. Wszystko zależy od wyboru OP dla jego gry. Na przykład zrobił to Diablo II. Więc nie byłbym tak surowy z częściami „nie możesz / potrzebujesz”. To tylko jedna z opcji, lepiej wyglądająca, ale zużywająca więcej pamięci RAM.
Kromster mówi o wsparciu Moniki
1
@KromStern Point jest, zawsze wygląda okropnie, jeśli to zrobisz.
API-Beast
Świetna odpowiedź. Czy jest to możliwe dzięki automatyzacji? Jeśli ktoś ma tysiące animowanych obrazów dla jednej postaci, nie jest możliwe ręczne wybranie każdej warstwy lub rozkładanie obrazu pojedynczo. Mimo to widzę pewne obejścia, które pomagają zautomatyzować to, jeśli renderowanie z 3D przy użyciu maskowania, ale niezależnie od tego, jest to nadal świetna odpowiedź.
Carter81
Potencjalnie możliwe jest zautomatyzowanie go przez znalezienie dominujących kolorów i wyodrębnienie ich (przy użyciu odwrotnego algorytmu „kolor do alfa”). Ale to nie tak, że kiedykolwiek wdrożyłem coś takiego.
API-Beast
Aby wyodrębnić rozjaśnienia, możesz wziąć wcześniej wyodrębnioną maskę i przefiltrować ją, aby pozostały tylko najjaśniejsze elementy.
API-Beast
3

Osobiście polecam użycie tekstur maski, aby osiągnąć to, czego chcesz. Zapewni to, że główna tekstura RGB24 zachowa oryginalną jakość kolorów bez poświęcania jakiejkolwiek precyzji. Zapewni również dużą swobodę artystyczną w łączeniu głównej tekstury z maską kolorów.

Każda maska ​​może być postrzegana jako tekstura w skali szarości, która liniowo interpoluje kolor tekstury podstawowej z kolorem niestandardowym. Powiedzmy, że pozwalasz użytkownikom na dostosowanie dwóch kolorów, moduł cieniujący pikseli będzie wyglądał mniej więcej tak:

Wejścia: MainTexture (RGB), Mask1Texture (A), Mask2Texture (A), Colour1 (float), Colour2 (float)

wyjście: (Mask1Texture + Mask2Texture) -MainTexture + Colour1 * Mask1Texture + Colour2 * Mask2Texture

Sugeruje to, że im bardziej maska ​​ma dużą wartość dla jednego piksela, tym mniej główna tekstura będzie miała wpływ na kolor wyjściowy tego piksela. Na przykład możesz przekształcić teksturę smoka w skalę szarości i usunąć wszystko oprócz skrzydeł, aby uzyskać niestandardowy kolor skrzydła bez względu na kolor ciała.

Użyłem tej techniki do gier mobilnych i nie wpłynie to na ogólną wydajność. Może kosztować o 33% więcej pamięci RAM na teksturę, ale kompromis w zakresie jakości jest prawdopodobnie tego wart.

Ps Jeśli myślisz tylko o użyciu jednego niestandardowego koloru, możesz po prostu użyć kanału Alpha głównej tekstury RGBA32 jako maski.

MrXee
źródło
2

możesz użyć palet kolorów i pozwolić graczowi edytować paletę. Jeśli używasz shaderów, możesz używać tekstur 1D jako palet, a oryginalną wartość szarości jako indeksu.

Aby przekonwertować obraz w prawdziwym kolorze na obraz o 255 kolorach, możesz wziąć wszystkie wartości kolorów pikseli i pogrupować je w przestrzeni kolorów 3d do 255 klastrów za pomocą algorytmu k-średnich. Lub użyj ogólnych narzędzi do konwersji obrazu. Następnie należy wspomnieć, że interpolacja tekstury wartości szarości będzie interpolacją wskaźników w teksturach kolorów. Może to doprowadzić do uzyskania kilku kolorów między dwoma teksturami oryginalnego obrazu. Można to rozwiązać, wyłączając interpolację (myślę, że nie chcesz tego robić) lub sortując paletę kolorów w użyteczny sposób.

Arne
źródło
Właśnie o tym myślałem. Możesz rozszerzyć odpowiedź na coś nieco bardziej kompletnego. Zasadniczo pozwalasz użytkownikowi wybrać dwa kolory (lub więcej lub mniej, ale ze względu na argument 2), stwórz teksturę 1D, która zniknie z dwóch kolorów. Użyj tekstury w skali szarości na geometrii, która służy jako odniesienie w teksturze 1D. Użytkownik nadal może ustawić brzydkie kolory, ale przynajmniej ma możliwość dokonywania ładnych kontrastowych wyborów kolorów.
wrosecrans
tak, możesz również uzyskać pełną 255 paletę kolorów z mniejszej liczby kolorów użytkownika, ale tutaj mogę tylko doradzić, aby wypróbować. Wiem, że wiele starych gier używało zmian w palecie kolorów, aby wprowadzać zmiany w swoich potworach. Myślę, że Diablo to zrobił.
Arne
1

możesz przekonwertować obraz na szary, ale nadal zapisać go z kanałami rgba. zapisz wartość masy w kanale alfa, a następnie użyj tego, aby zdecydować, ile barwnika zastosować na piksel. wagę tę można obliczyć na podstawie odległości koloru od bieli. im piksel jest bliżej bieli, tym mniej barwnika powinno się nakładać lub mniejsza powinna być jego waga. pozostawi większość pasemek z ich oryginalną lekkością, ale nałoży trochę na nią barwnika. ostateczny kolor piksela można następnie znaleźć, obliczając każdy kanał Ro + (Rd * Ao), gdzie Ro jest oryginalną czerwoną, Rd jest czerwonym kolorem barwnika, a Ao jest Alfą oryginału. więc wszystkie białe piksele nie otrzymują nowego koloru, a wszystkie czarne piksele przyjmują kolor barwnika.

Phil
źródło