Jak połączyć dwie kamery podczas podróży przez portal w Unity3D

18

Zanim przejdę do pytania, wiem, że najbardziej oczywistym rozwiązaniem byłoby użycie znormalizowanego portu widoku prostokątnego, jednak potrzebuję bardziej skomplikowanych kształtów niż prostokąta, i zajrzałem do korzystania z portu widoku prostokątnego i wydaje się, że nie bądź moim rozwiązaniem.

EDYCJA: Niektóre osoby były zdezorientowane moim pytaniem, pozwól mi przejść do bardziej szczegółowych szczegółów. wprowadź opis zdjęcia tutaj Co się dzieje, gdy gracz wchodzi do jednego portalu, tworzę sklonowany kontroler FPS i przenoszę go z drugiego. To daje mi dwie kamery i widok, który widzisz po prawej stronie powyżej. Pokazuje tylko jedną kamerę i przecina portal. Chcę czegoś podobnego do tegogdzie kamery łączą się, tworząc iluzję płynnego przejścia. Chcę usunąć wszystko z zielonego obrazu kontrolnego po lewej stronie na obrazku poniżej i zastąpić go innym aparatem. W ten sposób dostajesz część widoku kamery A wystającą z portalu, połączoną z częścią widoku kamery B wystającą z drugiego portalu, aby uzyskać jeden pełny obraz. A gdy poruszasz się po portalu, cięcie odpowiednio się zmienia.

Projektuję system portalu, mam wszystko na dole, łącznie z tym, aby gracz mógł płynnie poruszać się po portalu. Moim głównym problemem jest uzyskanie efektu mieszania kamer przez Valve. Potrzebuję dwóch kamer, aby płynnie się ze sobą łączyły, jakbyś szturchał głowę przez portal. I nie może to być po prostu prostokąt, musi pasować, jednak gracz patrzy przez portal.

W tej chwili moim najlepszym pomysłem jest wyświetlenie modułu cieniującego maski głębi za każdym portalem, a następnie ustawienie kamery z portalu, do którego podróżujesz, wyłącznie w zakresie głębi. Następnie jakoś zmiksuj dwie kamery. Moim głównym problemem jest ustalenie dokładnie, jak to zrobię, jak sprawić, by druga kamera renderowała tylko to, co znajduje się poza portalem, a resztą domyślnie była kamera 1, aby uzyskać jedną projekcję pełnoekranową.

Jeśli możesz podać mi pomysły lub wyjaśnić, jak mogę to zrobić za pomocą modułu cieniowania maski głębokości, który byłby ogromną pomocą. Będę nadal nad tym pracować i aktualizować, gdy będę się przebijać.

Timothy Williams
źródło
5
Czy potrafisz wyjaśnić, na czym polega „efekt mieszania aparatu przez Valve”? Zrozumiałem, że w renderowaniu portalu wystarczy jedna kamera. W grach pierwszoosobowych jest on dołączany do gracza i jest automatycznie przekształcany w nową lokalizację podczas przechodzenia przez portal wraz z graczem. W celu renderowania efektu portalu renderowana jest przekształcona kopia sceny. Można to również osiągnąć za pomocą drugiej kamery, ale nie powinno być potrzeby mieszania się między tymi kamerami.
sprzedać
1
Efekty wizualne już mam idealnie. Próbuję dowiedzieć się, jak uzyskać efekt przejścia przez portal. Mam już całą grafikę postaci i takie płynne poruszanie się, po prostu potrzebuję, aby wyglądała gładko z perspektywy pierwszej osoby.
Timothy Williams
1
Jestem pewien, że wiele osób chciałoby ci pomóc w rozwiązaniu problemu, gdyby zrozumieli, co to jest. Naprawdę musisz lepiej wyjaśnić ten problem, być może dodać zdjęcia lub nawet wideo wizualizujące, co jest nie tak.
sprzedać
2
Czy możesz dodać link do przykładowego filmu z efektem?
Mike Baxter,
2
Co się stanie, jeśli użyjesz tylko jednego aparatu / kontrolera FPS? Gdy kamera porusza się po portalu, możesz przekształcić go w nową lokalizację i orientację. Jeśli renderowanie portalu jest prawidłowe, przejście powinno być płynne i nie wymaga mieszania.
sprzedać

Odpowiedzi:

6

Zrozumienie problemu

Z tego, co widzę, problem, który opisujesz, jest wynikiem zbliżenia się płaszczyzny kamery do płaszczyzny zdefiniowanej przez portal. Podczas tego skrzyżowania możesz zobaczyć za ścianą portalu.

Jest to podobne do problemu występującego w innych grach, gdy gracz właśnie przechodzi z poziomu wody do podwodnej. Jeśli kamera znajduje się tuż nad powierzchnią wody, nie jest stosowany żaden efekt przetwarzania końcowego w celu zaciemnienia widoku gracza (ciemność, rozmycie i kolor niebieski). Więc jeśli dno bliskiego samolotu znajduje się tuż pod wodą, gracz może wyraźnie widzieć pod wodą.

Jeśli mam rację, możesz to potwierdzić, zmieniając położenie tej płaszczyzny podczas definiowania macierzy projekcji. Wraz ze wzrostem odległości od punktu początkowego kamery do bliskiej płaszczyzny powinien wzrosnąć problem.

Proste rozwiązanie

Przybliżenie bliskiego samolotu bardzo blisko aparatu powinno prawie wyeliminować ten problem. To rozwiązanie nie jest kompletne, ale przyniesie wystarczająco dobry wynik w zdecydowanej większości przypadków i jest wydajne.

Pełne rozwiązanie

Jeśli samo zbliżenie bliskiej płaszczyzny bliżej kamery nie jest wystarczające, możesz utworzyć „maskę”, aby połączyć obrazy generowane przez renderowanie sceny z perspektywy gracza i portalu.

Zakładając, że zezwalasz tylko na stosowanie portali do płaskich powierzchni, możesz obliczyć linię przecięcia między bliską płaszczyzną kamery a płaszczyzną zdefiniowaną przez portal (lub ścianę, na której leży). Ta linia podzieli ekran na dwie części. Określenie, po której stronie linii znajduje się piksel ekranowy, poinformuje Cię, który obraz renderowania ma zostać użyty, obraz portalu lub obraz z kamery odtwarzacza.

Należy pamiętać, że jeśli ten problem występuje, fragment widoku z kamery musi znajdować się całkowicie w obrębie portalu, aby linia przecięcia zawsze była całkowicie przecinana od jednej krawędzi ekranu do drugiej.

Ten link powinien pomóc matematyce znaleźć linię. Poniższy kod powinien być z grubsza poprawny.

Linia przecięcia jest definiowana za pomocą punktu na linii i kierunku linii. Poniżej kierunku przecięcia obliczany jest na podstawie iloczynu poprzecznego portalu normalnego i kierunku widoku kamery (normalna płaszczyzna w pobliżu płaszczyzny). Punkt na linii podaje się, rzucając promień z punktu na bliskiej płaszczyźnie bezpośrednio w kierunku płaszczyzny portalu (wzdłuż normalnego portalu) i znajdując punkt przecięcia.

Vector3 intersectionDir = Vector3.cross(portalNorm, viewDir);
Ray ray = new Ray(camPos + viewDir * camNearPlaneDist, portalNorm);
Vector3 intersectionPos = ray.intersects(new Plane(portalVert1, portalVert2, portalVert3);

Upewnij się, że viewDir jest wektorem jednostkowym. portalVert1, 2 i 3 to tylko 3 z 4 wierzchołków użytych do kalkomanii portalu lub powierzchni, na której się znajduje. Istnieją inne sposoby zdefiniowania płaszczyzny, na której leży portal, ale zakładam, że jest to najłatwiej dostępna informacja.

Gdy masz już te dwa wektory do zdefiniowania linii przecięcia, pomnóż każdy przez widok, a następnie macierze projekcji, aby uzyskać je w przestrzeni ekranu.

Następnie można użyć modułu cieniującego po zmieszaniu tych obrazów. Wybierz obraz, który ma być użyty na każdym pikselu, określając, po której stronie linii podziału znajduje się bieżący piksel. Odbywa się to poprzez przyjęcie pozycji piksela (która jest również pozycją, której używasz do wyszukiwania tekstu docelowego renderowania) i wykonywanie;

float d = (pixelX - intersectionPos.X) * intersectionDir.Y - (pixelY - intersectionPos.Y) * intersectionDir.X;

Strona jest podawana przez to, czy d jest większe czy mniejsze niż 0. Jeśli dokładnie wynosi 0, to jesteś na linii.

Aby zapoznać się z matematyką powyżej, zobacz to .

Tej metody można również użyć podczas tworzenia maski głębokości / bufora szablonu do użycia przed renderowaniem z perspektywy portalu. Możesz utworzyć quad pełnoekranowy i użyć linii, aby go pokroić.

OriginalDaemon
źródło
Samolot z krótkim klipem był dobrym pomysłem, ale nie do końca tym, czego szukam. Ta druga część jest jednak interesującym podejściem. Obecnie używam modułu cieniującego do maskowania głębokości na wszystkich elementach za wychodzącą płaszczyzną portalu, a następnie ustawiam tylko flagi głębokości wychodzącej kamery. To sprawia, że ​​każda część wychodzącej kamery wychodzącej z portalu rysuje na ekranie, a wchodząca kamera rysuje na masce głębokości, więc tworzy jeden obraz, mieszając części każdej kamery, która wystaje z niego odpowiedni portal. Jedynym problemem jest to, że dostaję kilka drobnych problemów z przycinaniem i
Timothy Williams
lekkie szarpnięcie, gdy gracz się porusza. Przywołany przez ciebie pomysł brzmi dość obiecująco. Zasadniczo muszę więc obliczyć linię wzdłuż ekranu, na której przecinają się kamera w pobliżu płaszczyzny i płaszczyzna portalowa, kierunek daje mi kierunek, w którym linia biegnie, a punktem są różne punkty linii. Jak miałbym wtedy określić w module cieniującym / skrypcie, po której stronie linii podziału leży piksel?
Timothy Williams
Zaktualizowałem nieco odpowiedź, aby podać podstawowy kod. Spróbuj zmienić widok w pobliżu odległości płaszczyzny odcinania, aby potwierdzić problem. Może to również być jak najmniejsze. Pamiętaj, spraw, aby działał, działał prawidłowo, a następnie szybko działał.
OriginalDaemon
Testowałem zmianę odległości zbliżonej do płaszczyzny odcinania, co nieco poprawiło problem, ale jak napisał artykuł Mell, nie rozwiązuje problemu podczas przebijania. Nadal mam wrażenie, że linia skrzyżowania może zadziałać, więc wypróbuję ją. Zajmę się również nieco bardziej tym artykułem, który opublikował Mell. W końcu będzie sprowadzają się do tego, czy maska głębokość jest większa lub linia przecięcia jest szybsze
Timothy Williams
3

Sugerowane odpowiedzi były bardzo dobre, ale ostatecznie wybrałem inną technikę przy użyciu maski głębokości.

Weź TYLNY skrypt i moduł cieniujący, umieścisz skrypt na każdym obiekcie z rendererem w twojej scenie i ustawisz kolejkę renderowania na 3020 (opublikuję skrypt, aby ułatwić to później).

Następnie tworzysz pudełko samolotów (wszystkie skierowane do wewnątrz, na zdjęciu nie widzisz boku pudełka najbliżej ciebie, ale kiedy jesteś w środku, powinieneś zobaczyć szary kolor) ZA OBIE portalami w ten sposób: wprowadź opis zdjęcia tutaj i ustaw ich na specjalnej warstwie (wybrałem dla mnie „DepthMask”), a następnie dodajesz materiał z shaderem powyżej. wprowadź opis zdjęcia tutaj

Następnie weź główny aparat i odznacz swoją warstwę specjalną z jej maski wygładzającej (odznaczyłem warstwę DepthMask) i ustaw głębokość na 0. wprowadź opis zdjęcia tutaj

Następnie podczas teleportacji i klonowania kamery ustaw wyraźne flagi drugiego aparatu na „Tylko głębokość”, a jego głębokość na 1. wprowadź opis zdjęcia tutaj

Następnie uzyskuje się płynny ekran łączony między dwoma widokami kamery.

Timothy Williams
źródło