Muszę napisać własny programowy rasterizer 3d i do tej pory jestem w stanie rzutować mój model 3d wykonany z trójkątów na przestrzeń 2d:
Obracam, tłumaczę i rzutuję moje punkty, aby uzyskać przestrzenną reprezentację każdego trójkąta. Następnie biorę 3 punkty trójkąta i implementuję algorytm skanowania (używając interpolacji liniowej), aby znaleźć wszystkie punkty [x] [y] wzdłuż krawędzi (lewej i prawej) trójkątów, aby móc skanować trójkąt w poziomie, rząd po rzędzie i wypełnij go pikselami.
To działa. Tyle, że muszę również zaimplementować buforowanie Z. Oznacza to, że znając obrócone i przetłumaczone współrzędne z 3 wierzchołków trójkąta, muszę interpolować współrzędną z dla wszystkich innych punktów, które znajduję za pomocą mojego algorytmu skanowania.
Koncepcja wydaje się dość jasna, po raz pierwszy znajduję Za i Zb z tymi obliczeniami:
var Z_Slope = (bottom_point_z - top_point_z) / (bottom_point_y - top_point_y);
var Za = top_point_z + ((current_point_y - top_point_y) * Z_Slope);
Następnie dla każdej Zp wykonuję tę samą interpolację w poziomie:
var Z_Slope = (right_z - left_z) / (right_x - left_x);
var Zp = left_z + ((current_point_x - left_x) * Z_Slope);
A jeśli bieżący z jest bliżej przeglądarki niż poprzedni z pod tym indeksem, Później zapisz kolor do bufora kolorów ORAZ napisz nowy z do bufora z. (mój układ współrzędnych to x: lewy -> prawy; y: górny -> dolny; z: twoja twarz -> ekran komputera;)
Problem polega na tym, że szaleje. Projekt jest tutaj i jeśli wybrać „Z buforowane” przycisk opcji, zobaczysz wyniki ... ( uwaga, że mogę używać algorytmu malarza (-only- narysować szkielet) w trybie „Z-buforowanej” do celów debugowania )
PS: Przeczytałem tutaj, że z = 1/z
przed interpolacją musisz przekształcić litery Z w ich odwrotność (znaczenie ). Próbowałem tego i wydaje się, że nie ma zmian. czego mi brakuje? (czy ktokolwiek mógłby wyjaśnić, gdzie dokładnie trzeba zmienić z na 1 / z i gdzie (jeśli), aby go odwrócić?)
[EDYCJA] Oto kilka danych o tym, jakie maksymalne i minimalne wartości Z otrzymuję:
max z: 1; min z: -1; //<-- obvious, original z of the vertices of the triangles
max z: 7.197753398761272; min z: 3.791703256899924; //<-- z of the points that were drawn to screen (you know, after rotation, translation), by the scanline with zbuffer, gotten with interpolation but not 1/z.
max z: 0.2649908532179404; min z: 0.13849507306889008;//<-- same as above except I interpolated 1/z instead of z.
//yes, I am aware that changing z to 1/z means flipping the comparison in the zBuffer check. otherwise nothing gets drawn.
Zanim przejdę do starannego debugowania, czy ktoś może potwierdzić, że moja koncepcja do tej pory jest poprawna?
[EDIT2]
Rozwiązałem buforowanie Z. Jak się okazuje, kolejność rysowania wcale nie była pomieszana. Współrzędne Z były obliczane poprawnie.
Problem polegał na tym, że próbując zwiększyć częstotliwość klatek, rysowałem pola 4px / 4px, co 4 piksele, zamiast rzeczywistych pikseli na ekranie. Rysowałem więc 16 pikseli na piksel, ale sprawdzałem bufor Z tylko dla jednego z nich. Jestem takim cyckiem.
TL / DR: Pytanie nadal brzmi: jak / dlaczego / kiedy trzeba używać odwrotności Z (jak w 1 / z) zamiast Z? Ponieważ teraz wszystko działa w obie strony. (nie ma zauważalnej różnicy).