Jakiego rodzaju algorytmu cieniowania można użyć do tworzenia takich cieni?
ten, który tworzę, jest podobny, ale wszystko odbywa się za pomocą interfejsu API rysowania 2D opartego na OpenGL, więc nie ma współrzędnej Z.
Ponadto, dla samej ręki, naprawdę chciałbym uzyskać zacienione odczucie, jak tutaj:
Po prostu nie jestem pewien, jak uzyskać zacieniony wygląd.
Liczba kart musi się zmienić, a karty zostaną rzucone na stół, więc nie mogę użyć żadnego rodzaju lekkiej mapy.
Jakiego rodzaju algorytmów powinienem szukać (oprócz rozmycia, które wiem, że muszę zrobić?)
Dzięki
Aktualizacja
Tworzę grę karcianą 2D. Chcę dodać przesunięcie cienia w stosunku do kart, trochę jak:
Myślę o tym:
- Zachowaj teksturę tego samego rozmiaru co bufor buforowy.
Narysuj ciemne prostokąty jako prowizoryczne karty do tej tekstury.
Rozmyj tę teksturę.
- Narysuj moje karty do tej tekstury.
- Zrób dodatkowe oświetlenie kart.
- Narysuj tę teksturę na backbufferze.
Moje pytania to:
Czy to właściwy sposób, aby to zrobić?
Czy istnieje sposób, aby to zrobić bez renderowania do tekstury (utrzymanie bitmapy
tak dużej jak backbuffer)?Czy można bezpiecznie założyć, że maksymalny rozmiar tekstury nie zostanie
przekroczony przez rozmiar bufora tylnego? (Mam na myśli to, że jeśli backbuffer
ma wymiary 2000 x 3000 , to spokojnie można powiedzieć, że mogę utworzyć teksturę w
pamięci wideo o tym rozmiarze?
Dzięki
źródło
Odpowiedzi:
Myślę, że wszyscy dają zbyt skomplikowane rozwiązania tego problemu ...
Najpierw mamy kartę (lub cokolwiek, co chcesz narysować), przedstawione tutaj przez (a). Następnie bierzemy kopię, wypełniamy ją na czarno i uruchamiamy na niej rozmycie gaussowskie (b). Wszystko to dzieje się w Photoshopie lub dowolnym ulubionym narzędziu artystycznym.
Następnie, w grze, gdy chcemy narysować kartę, najpierw narysuj zamazany czarny obraz z mieszanką multiplikatywną (lub alfa), przesunąć nieco w pewnym kierunku, a następnie narysuj kartę na nim. Voilá.
Aby uzyskać więcej sztuczek, możesz przełączać się między renderowaniem cieni i kart, aby uzyskać efekt, jak (d), lub najpierw narysuj wszystkie cienie, a następnie karty, jak w (e) (pokolorowałem karty w przypadku (e), aby pokazać, że nadal są osobni =)
Najlepiej też nie używać czystej czerni (lub pełnej alfa) do tworzenia cieni w celu uzyskania bardziej subtelnych, przezroczystych cieni.
źródło
Pierwszy nie jest zbyt trudny. Jeśli renderujesz kanał alfa dla ręki kart (która może być tak prosta jak czerń dla piksela z kartą i biała dla przezroczystości), możesz wykonać dowolne rozmycie, tylko na kanale alfa, i następnie przesuń go i użyj tego do sterowania oświetleniem stołu. (Prawdopodobnie, jeśli nie masz bufora Z, najpierw musisz wyrenderować gdzieś kanał alfa poza ekranem, a następnie zrobić tabelę z maską, a następnie renderować rzeczywiste karty.)
Drugi wygląda trochę jak SSAO (okluzja otoczenia w przestrzeni ekranu). Ta technika wymaga współrzędnej Z. Jeśli jednak nie masz różnych kątów między kartami (co zgaduję, jeśli nie masz bufora Z), prawdopodobnie możesz zrobić całkiem dobre przybliżenie, renderując cień (jak pierwszy) dla każdej karty karta. Wydajność może być jednak trochę trudna - każdy samolot potrzebowałby niewyraźnego kanału alfa dla wszystkich samolotów nad nim, a jeśli na stole znajduje się wiązka kart, może to być kilka pasaży renderowania.
źródło
Czy nie możesz zrobić mapy cienia? Renderuj scenę do fbo. Zapisz tylko wartości głębokości i sprawdź normalną wartość głębokości w module cieniującym, aby sprawdzić, czy cień powinien być renderowany, czy nie.
źródło
Poniższy proces nie wymaga docelowego renderowania poza ekranem. W ten sposób uzyskuje się jednak wymóg, aby najpierw narysować tabelę . Przynajmniej piksele nie zostaną narysowane przed rysowaniem tabeli. Wymaga również, aby sam stół był jednym, pojedynczym, nie nakładającym się elementem: obrazem.
Ponadto bufor ramki wymaga komponentu alfa.
Uzyskaj obraz w skali szarości karty. Spraw, aby był niewyraźny wokół krawędzi, prawdopodobnie zwiększając jego rozmiar. To jest twój obraz karty cienia. Pamiętaj, że jest to obraz jednokanałowy. Gdy uzyskasz dostęp do tej tekstury w module cieniującym, upewnij się, że umieściłeś pojedynczą wartość w składniku alfa. Można to zrobić w shaderze lub w innym miejscu.
Wartość 0,0 na obrazie oznacza, że nie ma cienia. Wartość 1,0 na obrazie oznacza całkowity cień . To znaczy, zupełnie czarna. Prawdopodobnie chcesz mieć wartość około 0,5 jako swój najciemniejszy kolor.
Wyczyść ekran tak, aby alfa było ustawione na zero .
Przed renderowaniem czegokolwiek (lub przynajmniej czegokolwiek, co będzie renderowane „pod” stołem), dla każdej karty, render rozmytą teksturę, przesunięcie względem rzeczywistej pozycji karty (ale z tą samą orientacją). Kolor wyjściowy modułu cieniującego powinien mieć następującą konfigurację mieszania (w języku OpenGL):
Ten tryb mieszania służy do tego, aby nakładające się cienie nie stawały się coraz ciemniejsze lub jaśniejsze. Po prostu przyjmuje najciemniejszą wartość zapisaną na tym pikselu. Powinno dobrze wyglądać.
Powinieneś również użyć maski zapisu kolorów, aby wyłączyć zapisywanie kolorów.
Renderuj stół. W takim przypadku mieszanie należy skonfigurować w następujący sposób:
Jeśli ograniczenia są dla ciebie zbyt restrykcyjne, musisz użyć celu renderowania. Odbywa się to w następujący sposób:
Utwórz obraz karty cienia jak poprzednio.
Najpierw renderuj cienie. Powiąż bufor cieniowania ramki (który musi być tylko obrazem jednokanałowym, jeśli twój sprzęt może renderować do jednego z nich). Wyczyść jego wartość do zera.
Dla każdej karty renderuj obraz karty cienia z przesunięciem jak poprzednio. Twój moduł cieniujący powinien zapisać tę samą wartość do wszystkich czterech składników koloru wyjściowego. Tryb mieszania powinien być ponownie
glBlendEquation(GL_MAX)
.Wróć do zwykłego bufora ramki. Narysuj wszystko, co chcesz ukryć.
Teraz narysuj kwadrat na pełnym ekranie z renderowanym przez nas obrazem cienia. Moduł cieniujący powinien przechowywać tekst pobrany z obrazu cienia w alfa wyniku; RGB nie ma znaczenia. Tryb mieszania powinien być:
źródło
Użyłbym bufora szablonów. Wyczyść to do 1 (najlepiej w tym samym czasie, gdy wyczyścisz głębokość), narysuj swój stół. Następnie włącz test szablonu, narysuj cienie za pomocą rozmytej tekstury prostokąta, zwiększając, jeśli szablon i głębokość przejdą, nie robiąc nic, jeśli szablon się nie powiedzie, nic, jeśli głębokość się nie powiedzie, i ustaw func szablonu na GL_EQUAL (ref 1, maska 0xff), wyłącz test szablonu . (Nie przetestowałem tego w pełni, ale pochodzi on z kodu, który działa podobnie i powinien działać dobrze; być może trzeba będzie poprawić parametry). Następnie narysuj wszystko inne.
Połączenia będą:
Jedyny raz może to powodować problemy, jeśli masz dwie rozmyte krawędzie, które lekko się pokrywają; w przeciwnym razie nie potrzebuje nic szczególnego poza podstawową ofertą OpenGL 1.1 i będzie działał na każdym sprzęcie (spodziewaj się być może starych kart 3DFX, które zakładam, że tak naprawdę nie martwisz się o wsparcie ...)
Drugą alternatywą, która powinna działać bardzo dobrze w grze niekrytycznej pod względem wydajności, jest glCopyTexSubImage2D. Działa to również z teksturą mniejszą niż backbuffer i jest również dobrze obsługiwany na wszystkich urządzeniach (jest to część OpenGL 1.1 i Doom 3 go używało, więc możesz oczekiwać, że wsparcie będzie bardzo dobre).
Podstawowa konfiguracja wyglądałaby następująco:
Powinno to również działać bardzo dobrze, jest nieco bardziej intensywne w GPU niż metoda bufora matrycowego, ale poprawnie obsługuje nakładającą się obudowę i - jak powiedziałem - myślę, że gra taka jak Twoja będzie miała moc GPU do wypalenia, nawet na niskim poziomie karta.
źródło