Tworzę siatkę proceduralną na podstawie krzywej, a rozmiar siatki zmniejsza się na całej krzywej, jak widać poniżej.
Problem polega na tym, że UV zmienia się w zygzakowate, gdy zmienia się rozmiar (działa idealnie, gdy rozmiar siatki jest taki sam na całej krzywej).
Vertices.Add(R);
Vertices.Add(L);
UVs.Add(new Vector2(0f, (float)id / count));
UVs.Add(new Vector2(1f, (float)id / count));
start = Vertices.Count - 4;
Triangles.Add(start + 0);
Triangles.Add(start + 2);
Triangles.Add(start + 1);
Triangles.Add(start + 1);
Triangles.Add(start + 2);
Triangles.Add(start + 3);
mesh.vertices = Vertices.ToArray();
//mesh.normals = normales;
mesh.uv = UVs.ToArray();
mesh.triangles = Triangles.ToArray();
Jak mogę to naprawić?
unity
procedural-generation
mesh
uv-mapping
fkkcloud
źródło
źródło
id
icount
? Co maUVs.ToArray()
zrobić? Jak przesyłasz na kartę wierzchołki i współrzędne tekstury?id
jest indeksem bieżącego segmentu ze wszystkich poprzeczek wzdłuż paska, gdziecount
łącznie są.List<T>.ToArray()
zwraca tablicę wszystkich wpisów na liście (więc tutaj, aVector2[]
). Te bufory danych są udostępniane systemowi renderującemu, przypisując je doMesh
instancjimesh
w kilku ostatnich wierszach. Ale nic z tego nie jest szczególnie interesującą częścią kodu: jak wybierane są punkty wierzchołków. Te szczegóły byłyby bardziej przydatne do zobaczenia. ;)count
faktycznie oznacza to wierzchołki zamiast wielokątów lub odwrotnie. Tylko upewnienie się, że wszystko, co naszym zdaniem się dzieje, naprawdę się dzieje.Odpowiedzi:
Typowe mapowanie UV to tak zwana transformacja afiniczna . Oznacza to, że mapowanie każdego trójkąta między przestrzenią 3D a przestrzenią tekstury może obejmować obrót, translację, skalowanie / squash i pochylenie (tj. Wszystko, co możemy zrobić z jednorodnym zwielokrotnieniem macierzy)
Rzecz w transformacjach afinicznych polega na tym, że są one jednolite w całej swojej dziedzinie - obrót, translacja, skala i pochylenie, które stosujemy do tekstury w pobliżu wierzchołka A, jest takie samo, jak to, co stosujemy w pobliżu wierzchołka B, w obrębie dowolnego trójkąta. Linie, które są równoległe w jednej przestrzeni, zostaną odwzorowane na linie równoległe w drugiej, nigdy nie będą zbieżne / rozbieżne.
Ale stopniowe zwężanie, które próbujesz zastosować, nie jest jednolite - odwzorowuje równoległe linie w teksturze na zbieżne linie na siatce. Oznacza to, że skala tekstury mierzona w paśmie zmienia się ciągle, gdy przesuwa się w dół paska. To więcej, niż mogą dokładnie reprezentować afiniczne przekształcenia 2D UV mapping: interpolacja współrzędnych UV uv między sąsiadującymi wierzchołkami uzyska jedną spójną skalę na całej krawędzi, nawet krawędź ukośną, która powinna się zmniejszać w miarę przesuwania się w dół paska. To niedopasowanie jest tym, co tworzy ten warczący zygzak.
Ten problem pojawia się za każdym razem, gdy chcemy odwzorować prostokąt na trapezoid - równoległe boki do zbieżnych boków: po prostu nie ma transformacji afinicznej, która to robi, więc musimy to przybliżać fragmentarycznie, co prowadzi do widocznych szwów.
W większości przypadków można zminimalizować efekt, dodając więcej geometrii. Zwiększenie liczby podziałów wzdłuż długości paska i podzielenie paska na dwa lub więcej segmentów wzdłuż jego szerokości, przy przekątnych trójkątów ułożonych w wzór w jodełkę, może sprawić, że efekt będzie znacznie mniej zauważalny. Zawsze będzie jednak obecny do pewnego stopnia, dopóki używamy transformacji afinicznych.
Ale jest na to sposób. Możemy użyć tej samej sztuczki, której używamy do renderowania 3D, aby narysować trapezoidy w perspektywie, biorąc pod uwagę prostokątne ściany i podłogi: używamy współrzędnych projekcyjnych !
Teksturowanie afiniczne:
Teksturowanie projekcyjne:
Aby to zrobić, musimy dodać trzecią współrzędną UV (UVW) i zmodyfikować nasze shadery.
Biorąc pod uwagę współczynnik skali w każdym punkcie (powiedzmy, równy szerokości paska w tym miejscu), możesz zbudować współrzędną projekcyjną 3D uvw ze swojej zwykłej współrzędnej 2D UV w ten sposób:
Aby zastosować te współrzędne 3D UVV do swojej siatki, musisz użyć siatki przeciążeniowej Vector3.SetUVs (kanał wewnętrzny, lista UV)
I pamiętaj, aby zmienić strukturę wejściową modułu cieniującego, aby oczekiwać współrzędnej tekstury 3D (pokazanej tutaj przy użyciu domyślnego nieoświetlonego modułu cieniującego):
Konieczne będzie również wycięcie makra TRANSFORM_TEX w module cieniującym wierzchołki, ponieważ oczekuje uv 2D:
Wreszcie, aby powrócić do współrzędnej tekstury 2D do próbkowania tekstury, wystarczy podzielić przez trzecią współrzędną w module cieniującym fragmenty :
Ponieważ wykonaliśmy tę współrzędną 3D uvw z pożądanej współrzędnej 2D przez pomnożenie przez tę samą liczbę, dwie operacje anulują się i wracamy do naszej pierwotnej pożądanej współrzędnej 2D, ale teraz z interpolacją nieliniową między wierzchołkami. :RE
Ważne jest, aby wykonać ten podział na fragment, a nie w module cieniującym wierzchołki. Jeśli zostanie to zrobione w odniesieniu do wierzchołka, wrócimy do interpolacji wynikowych współrzędnych liniowo wzdłuż każdej krawędzi i utraciliśmy nieliniowość, którą próbowaliśmy wprowadzić za pomocą współrzędnej rzutowej!
źródło