Co robi karta graficzna z czwartym elementem wektora jako końcową pozycją?

25

Z tego pytania wynika, że ​​potrzebujesz czteroelementowego wektora pozycji, ponieważ łatwiej jest zmodyfikować jego pozycję za pomocą mnożenia macierzy.

Samo w sobie oznaczałoby to, że czwarty element powinien być po prostu zignorowany, gdy rozważa się go jako reprezentację punktu 3D (zakładając brak transformacji), ale wiem, że to nie jest prawda, jak gdy dostarczam wektor4 do GPU, jeśli czwarty element nie jest jeden, nie jest renderowany - dlaczego?

Jakie znaczenie ma czwarty element, gdy jest już w rasterizerze?

EDYCJA : Podczas przeglądu to pytanie było nieco źle sformułowane; dokładniej byłoby powiedzieć w drugim akapicie: „jeśli wartość czwartego elementu nie mieści się w określonym zakresie, nie jest renderowana„ poprawnie ”/„ zgodnie z oczekiwaniami ””.

sebf
źródło
czy wektor4 o współrzędnych (x, y, z, 0,5) daje takie same wyniki wektora4 o współrzędnych (2x, 2y, 2z, 1)?
FxIII
@FxIII, nie byłem w stanie dokładnie tego odtworzyć, ale masz rację, to było niepoprawne stwierdzenie ogólne wprowadzone w moim oryginalnym poście, po kilku eksperymentach zaktualizowałem je.
sebf

Odpowiedzi:

23

Czwarty element to sztuczka pozwalająca śledzić rzut perspektywiczny. Kiedy wykonujesz rzut perspektywiczny, chcesz podzielić przez z: x '= x / z, y' = y / z, ale nie jest to operacja, którą można wykonać za pomocą macierzy 3x3 działającej na wektorze x, y, z. Sztuczka, która stała się standardem w tym zakresie, polega na dodaniu czwartej współrzędnej, w, i zadeklarowaniu, że x, y, z będzie zawsze dzielone przez w po zastosowaniu wszystkich transformacji i przed rasteryzacją.

Rzut perspektywiczny jest następnie realizowany przez macierz, która przesuwa z do w, tak że dzielimy przez z. Ale daje także elastyczność, aby pozostawić w = 1,0, jeśli nie chcesz dokonywać podziału; na przykład, jeśli chcesz tylko projekcji równoległej, obrotu lub cokolwiek innego.

Możliwość kodowania pozycji jako w = 1, kierunków jako w = 0 i użycia czwartego wiersza / kolumny macierzy do tłumaczenia jest dobrą zaletą uboczną, ale nie jest głównym powodem dodawania w. Można zastosować transformacje afiniczne (macierz 3x3 plus 3-komponentowy wektor translacji), aby uzyskać translację bez widoczności. (Trzeba będzie śledzić, jaka jest pozycja i jaki kierunek, i zastosować różne funkcje transformacji do każdej z nich; to trochę niewygodne, ale nie jest to naprawdę wielka sprawa).

(BTW, matematycznie, wektory rozszerzone o w są znane jako jednorodne współrzędne i żyją w miejscu zwanym przestrzenią rzutową . Jednak nie trzeba rozumieć wyższej matematyki, aby wykonać grafikę 3D.)

Nathan Reed
źródło
Ponownie jest nieco niepoprawne mówienie o wektorach i punktach w tych terminach, ponieważ pomiędzy punktami i wektorami występuje izomorfizm (punkt i wektor, które przenoszą początek do tego punktu, są tym samym bytem). Bardziej poprawne byłoby mówienie o punktach / wektorach (w! = 0) i (rzutowych) kierunkach (w = 0). W każdym razie niewłaściwe użycie terminu „wektor” jest dość skonsolidowanym standardem w języku bibliotek 3d.
FxIII
@FxIII: Poprawiony. Używanie „wektora” w standardowym znaczeniu matematycznym i jako synonimu „kierunek” w tym samym poście było mylące.
Nicol Bolas,
@FxIII i Nicol Bolas: Nie zgadzam się. Naprawdę kodujesz wektory jako w = 0 - w tym oba wektory, które tylko przedstawiają kierunek, oraz wektory, w których długość jest ważna. Na przykład można przekształcić wektor prędkości kątowej (kierunek = oś obrotu, długość = prędkość) obiektu między przestrzenią lokalną a przestrzenią świata za pomocą macierzy obiektu. Nie chcesz, aby prędkość kątowa dodawała do niej translację obiektu; chcesz tylko, aby został obrócony. Więc ustawiłeś w = 0. Nie widzę problemu?
Nathan Reed
@NathanReed Mam nadzieję, że mój post pomaga wyjaśnić tę kwestię, w dużej mierze jednak chodzi o definicje i niewłaściwe użycie terminu wektor oraz prymat algebry liniowej nad standardową terminologią bibliotek 3D. Oczywiście oba są dyskusyjne, ponieważ każda definicja i roszczenie o pierwszeństwo to
FxIII
@Nathan, widzę teraz wyraźnie cel czwartego elementu i sposób, w jaki zawarte w nim informacje są wykorzystywane przez rasterizer. Wielkie dzięki!
sebf
10

Próbując odpowiedzieć na odpowiedni komentarz Natana, zastanowiłem się, co może być przydatne, aby zrozumieć, co naprawdę dzieje się, gdy używasz wektorów w Przestrzeni Affine do reprezentowania wektorów 3D w standardowej Przestrzeni Euklidesowej.

Najpierw nazywam wektor tym, co ma współrzędne, więc punkt i wektor są tym samym bytem; wektor widzisz jako różnicę dwóch punktów: V = B - A ; V porusza A w B Ze względu A + V = A + B - A = B . Umieść A = 0 (początek), a otrzymasz V = B - 0 = B : punkt B i wektor, który porusza się 0do B są tym samym.

Nazwę „wektor” - w sensie używanym w większości bibliotek 3D - gdy wektor przestrzeni afinicznej ma w = 0.

Macierz jest używana, ponieważ pozwala przedstawić funkcję liniową w formie zwartej / eleganckiej / wydajnej, ale funkcje liniowe mają główną wadę, która nie może przekształcić początku: F ( 0 ) = 0, jeśli F chce być liniowy ( między innymi F (λ X ) = λF ( X ) i F ( A + B ) = F ( A ) + F ( B ))

Oznacza to, że nie możesz zbudować macierzy wykonującej tłumaczenie, ponieważ nigdy nie przeniesiesz wektora 0 . W grę wchodzi Affine Space . Przestrzeń afiniczna nadaje wymiar przestrzeni euklidesowej, więc przeszczepy można wykonywać za pomocą skalowania i rotacji.

Przestrzeń afiniczna jest przestrzenią rzutową w tym sensie, że można zbudować relację równoważności między wektorami afinicznymi i euklidesowymi, aby można było je pomylić (tak jak to zrobiliśmy z wierszami i wektorami). Wszystkie wektory afiniczne, które rzutują na początek w tym samym kierunku, mogą być postrzegane jako ten sam wektor euklidesowy.

Oznacza to, że wszystkie wektory o takich samych proporcjach we współrzędnych można uznać za równoważne:

Matematycznie:

równorzędność

tzn. każdy wektor afiniczny można zredukować do wersji kanonicznej, w której w = 1 (wybieramy spośród każdego równoważnego wektora ten, który najbardziej lubimy).

Wizualnie (euklidesowy 2D - afiniczny 3D):

równoważność wizualna

stąd środek „rzutowej” przestrzeni; Należy zauważyć, że tutaj przestrzeń euklidesowa to 2D (region cyjan)

Istnieje szczególny zestaw wektorów afinicznych, których nie można łatwo umieścić w ich wersji kanonicznej, która leży na (hiper) płaszczyźnie w = 0.

Możemy to pokazać wizualnie:

wprowadź opis zdjęcia tutaj

(powinieneś) zobaczyć, że podczas gdy w -> 0, rzutowany wektor do przestrzeni euklidesowej przechodzi do nieskończoności, ale do nieskończoności w określonym Kierunku .

Teraz jest jasne, że dodanie dwóch wektorów w przestrzeni rzutowej może prowadzić do problemów, jeśli weźmiesz pod uwagę wektor sumy jako rzutowany wektor w przestrzeni euklidesowej, to się dodaje, ponieważ zsumujesz składniki W w przestrzeni afinicznej, a następnie rzutujesz je na płaszczyzna euklidesowa (hiper).

Dlatego można sumować tylko „punkty” do „wektorów”, ponieważ „wektor” nie zmieni współrzędnej w „punktu”, jest to prawdą tylko dla „punktów”, gdzie w = 1:

wprowadź opis zdjęcia tutaj

Jak widzisz, zielony punkt jest tym uzyskanym przez dodanie dwóch wektorów afinicznych, które reprezentują cyjan „punkt” i wektor „V” , ale jeśli zastosujesz V do każdego wektora afinicznego w innej formie niż kanoniczny, otrzymasz złe wyniki (czerwony „punkt”).

Widzisz, że Przestrzeń Affine nie można użyć w sposób przejrzysty do opisania operacji na przestrzeniach euklidesowych, a niewłaściwe użycie terminu „wektor” ma sens pod (ścisłym) ograniczeniem sum obliczeniowych tylko dla kanonicznych wektorów rzutowych .

Mówiąc to, całkiem rozsądnie jest myśleć, że GPU zakłada, że Vector4 musi mieć w = 0 lub w = 1, chyba że naprawdę wiesz, co robisz.

FxIII
źródło
Bardzo trudno było wybrać jedną odpowiedź na to pytanie, ponieważ wszystkie one przyczyniły się do zrozumienia, w jaki sposób wykorzystywany jest związek czwartego komponentu i dlaczego jest on potrzebny. Twoje wyjaśnienie przestrzeni euklidesowej i afinicznej jest bardzo pomocne, z pewnością nie zrozumiałbym tego tak, jak teraz, bez tego poziomu szczegółowości. Dziękuję Ci bardzo!
sebf
+1 za dobre wyjaśnienie (i diagramy!) Przestrzeni rzutowej. Jednak przestrzeń afiniczna i przestrzeń rzutowa to nie to samo (zobacz definicję przestrzeni afinicznej w Wikipedii ). Być może dobrym sposobem na powiedzenie tego jest: rzutowa 3-spacja i afiniczna 3-spacja mogą być zarówno osadzone w R ^ 4, ale osadzenia nie są całkowicie zgodne. Kodowanie wektorów z przestrzeni afinicznej jako w = 0 jest możliwe i użyteczne, ale nie ma znaczenia z projekcyjnego punktu widzenia. Podobnie kierunki rzutowania (punkty w nieskończoności) nie mają znaczenia z afinicznego punktu widzenia.
Nathan Reed,
1

Załóżmy wektor taki jak (x, y, z, w). Ten wektor ma 4 składowe x (współrzędna x w przestrzeni), y (współrzędna y w przestrzeni), z (współrzędna z w przestrzeni) oraz interesujący i tajemniczy składnik w. W rzeczywistości większość gier 3D działa w przestrzeni 4d, zwanej także przestrzenią jednorodną 4d. Jest kilka oczywistych korzyści z tego ->

1> Pomaga nam łączyć macierze translacji i rotacji w jedną, ale możesz zastanawiać się, jaki jest pożytek, możemy po prostu pomnożyć macierz translacji i rotacji i to wszystko, ale nic więcej. Jeśli nie mamy w składniku we wszystkich naszych wektorach, a następnie, gdy pomnożymy wektor 3d (xyz) do połączonej macierzy translacji i obrotu w dowolny sposób, nieświadomie skalujemy wartości za pomocą x, y lub z (tak działa mnożenie macierzy) i to będzie prawdopodobnie uszkodził macierz pozycji (część translacji połączonej macierzy) z powodu skalowania. Aby rozwiązać ten problem, wprowadzono wektor składowy 4 i ten składnik wektora (w) będzie miał wartość 1,0 w 99% przypadków. Ten składnik 4 pozwala nam mieć nieskalowane wartości pozycji (tłumaczenie). Macierz jest reprezentowana jako->

 [x y z w] [rx1 rx2 rx3 1]
           [ry1 ry2 ry3 1]
           [rz1 rz2 rz3 1]
           [px  py  pz  1]

a następnie mamy prostą, ale potężną macierz. :)

2> Kopiujemy wartość z do komponentu w na etapie projekcji perspektywicznej i dzielimy z nią x, y. W ten sposób obiekty stają się krótsze, gdy oddalają się od ekranu.

gamePro
źródło
Dziękuję Ci! Coraz bardziej dostrzegam konieczność użycia czwartego komponentu w każdej naprawdę użytecznej reprezentacji bytu w przestrzeni 3D.
sebf