Jak obchodzić się z obcinanymi wierzchołkami, które są bliżej oka niż w pobliżu płaszczyzny obcinania?


13

Tworzę własny silnik 3D w JavaScript i używam tylko rysunku na płótnie, bez WebGL. To kolejny klon Minecrafta; Uwielbiam pudełka, nie oceniaj mnie.

Jak dotąd wszystko działa wspaniale, z wyjątkiem jednej rzeczy: w 3D, gdy niektóre wierzchołki wychodzą za bliską płaszczyznę tnącą, ich rzut na ekran wychodzi dziwnie (zakładając, że inne wierzchołki używane do śledzenia płaszczyzny znajdują się z przodu).

Próbowałem wyciąć te punkty, ale potem widzę koryta powierzchni wykorzystujących te wierzchołki. W WebGL / OpenGL karta graficzna zajmuje się tymi punktami, a płaszczyzna jest renderowana poprawnie, ale nie mam dostępu do sprzętu, więc sam muszę to kodować.

Nie jestem do końca pewien, co z tym zrobić, obecnie ostatnią rzeczą, jaka przyszła mi do głowy, jest odwrócenie projekcji punktów za zbliżającą się płaszczyzną tnącą gracza, co wydaje się logiczne, ponieważ muszę rzutować punkt na ekran przed nim wierzchołka.

Oto moje przemyślenia:

wprowadź opis zdjęcia tutaj

Oto kilka zdjęć ilustrujących to, co się dzieje:

wprowadź opis zdjęcia tutaj

Z daleka niebieskie pudełko renderuje się doskonale.

wprowadź opis zdjęcia tutaj

Kiedy niektóre wierzchołki znajdują się za płaszczyzną przycinania odtwarzacza, odwracam projekcję, ale nie wygląda to dobrze:

focalLength *= -1;
2d.x = x*focalLength/z;
2d.y = y*focalLength/z;

Zauważ, że szare pole z tyłu zostało całkowicie usunięte, ponieważ wszystkie wierzchołki użyte do narysowania jego twarzy znajdują się za graczem.

wprowadź opis zdjęcia tutaj

Tak dzieje się, gdy patrzysz w górę lub w dół.

Nie wiem, co sądzić o matematyce, mam nadzieję, że ktoś już napotkał ten sam problem i może mi pomóc.


1
Jeśli punkty znajdują się bliżej oka niż najbliższa płaszczyzna klipu, powinny zostać obcięte - i to może rzeczywiście pozwolić ujrzeć obiekt „przez”. To jest typowe zachowanie; kolizja zwykle zapobiega temu konkretnemu artefaktowi wizualnemu. Czy to jedyna rzecz nie tak z twoim rozwiązaniem przycinania?

@JoshPetrie: Rozumiem, że punkty muszą zostać obcięte, ale jeśli to zrobię, cały kwadrat zniknie jako jeden lub dwa z wierzchołków, przez które musi przejść procedura rysowania (na 2d) i gracz będzie mógł zobaczyć przez ten kwadrat. Chciałbym, aby były „na zewnątrz” płótna (na rzucie), aby kwadrat mógł być nadal rysowany. Nie jestem pewien, czy jestem wystarczająco jasny.
Elektrozawór

Jesteś - mówię, że jest to normalne zachowanie i chcesz temu zapobiec poprzez zapobieganie odtwarzacza z coraz to blisko jednej z kostek. Jeśli naprawdę chcesz to zrobić, powinieneś wyciąć, ale zrekonstruować trójkąty (prawdopodobnie). Będzie to nadal wyglądać nietypowo, szczególnie jeśli masz tekstury. Jeśli to, co mówię, nie ma sensu, możesz dołączyć do nas na czacie , abyśmy nie tworzyli naprawdę gadatliwego komentarza.

To, co mówisz, ma sens, rekonstrukcja zajmuje zbyt dużo czasu, więc to nie jest rozwiązanie. Miałem nadzieję, że istnieje sposób, aby nadal narysować ten wierzchołek na płaszczyźnie 2d, która była za odtwarzaczem, aby lineTo(x,y)można było wywołać tę funkcję, ale nie wiem, jak się zachowuje ... to dziwny wymiar, zgadzam się.
Elektrozawór

Wystarczy popatrzeć na tym kursie , to wyjaśnia, w jaki sposób obliczyć wycinek poszczególnych trójkątów i obiektów jako całość
ѕняєє ѕιиgнι

Odpowiedzi:


1

Celem bliskiej płaszczyzny tnącej jest to, że jest to płaszczyzna tnąca . Trójkąty znajdujące się poza płaszczyzną przycinania są przycinane : pocięte na kawałki, aby każdy pozostały kawałek znalazł się w obszarze przycinania.

Jeśli chcesz, możesz zignorować klip w pobliżu. Rzeczywiście OpenGL i D3D mogą całkowicie wyłączyć obcinanie w pobliżu płaszczyzny (chociaż bufor głębokości nadal ma minimalną wartość bliską). Problemem nie jest bliski klip.

Problem dotyczy wierzchołków znajdujących się za kamerą.

Nie można renderować trójkątów znajdujących się za kamerą. Nie z rzutowaniem perspektywicznym. Takie trójkąty nie mają sensu pod matematyką za rzutami perspektywicznymi. Co więcej, są one również poza otoczką.

Wyłączenie w pobliżu przycinania zmienia frustum w piramidę. Powodem, dla którego piramida zatrzymuje się w tym punkcie, jest to, że punkty nad piramidą znajdują się za wszystkimi czterema bokami piramidy. Tak więc każdy punkt za kamerą (czubek piramidy) znajduje się powyżej, poniżej, po lewej i po prawej stronie widocznego obszaru ekranu. Wszystko w tym samym czasie.

Jak powiedziałem: wierzchołki pod rzutowaniem perspektywicznym, które znajdują się za kamerą, nie mają sensu.

Musisz wdrożyć obcinanie. Musisz wykryć, kiedy jakikolwiek wierzchołek trójkąta w przestrzeni klipu ( przed podziałem perspektywy) znajduje się za kamerą. Jeśli tak, musisz przyciąć ten trójkąt, generując tylko trójkąty znajdujące się przed kamerą.

To nie jest prosty proces. Będzie to wymagało matematyki, która ma sens tylko wtedy, gdy masz pełne zrozumienie jednorodnych układów współrzędnych. Alternatywnie, możesz po prostu wyprostować dowolny trójkąt, jeśli jakikolwiek jego wierzchołek znajduje się za kamerą.


Do tej pory wycinałem cały trójkąt, ale potem widziałem płaszczyznę (patrz zdjęcia powyżej). Naprawdę potrzebowałem zdjęcia, aby zrozumieć, dlaczego nie ma to sensu geometrycznego. Jedynym rozwiązaniem jest obliczenie przecięcia linii z płaszczyzną, gdy jeden z wierzchołków znajduje się za płaszczyzną przycinającą, i użycie tego przecięcia do prześledzenia linii od wierzchołka znajdującego się z przodu, niestety jest to kosztowne.
Elektrozawór

0

Jeśli część trójkąta znajdująca się za bliską płaszczyzną mogłabyś sprawdzić, czy piksel znajduje się za płaszczyzną przycinającą?

Możesz traktować bliski samolot jak każdą inną płaszczyznę tnącą. Na przykład płaszczyzny obcinania są używane do takich rzeczy, jak płaszczyzny wodne (do odbić i załamań). Sądzę, że ta płaszczyzna odcinania będzie działać tak samo, jak płaszczyzna zbliżenia przycinania, i będzie przycinana na piksel.

Wiem, jak obsługiwać płaszczyzny obcinania w HLSL za pomocą DirectX, ale ich implementacja może być zastrzeżona. Jeśli możesz uzyskać informacje na ten temat, może to być pomocne.

Dodatkowo tutaj jest link, który może ci pomóc: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter42.html


Testowanie na piksel jest niezwykle kosztowne w interpretowanym języku, takim jak Javascript, teraz otrzymuję ledwo akceptowalną liczbę klatek na sekundę.
Elektrozawór
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.