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:
Vector3 uv3 = ((Vector3)uv2) * scale;
uv3.z = scale;
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):
struct appdata
{
float4 vertex : POSITION;
float3 uv : TEXCOORD0; // Change float2 to float 3.
};
// Also do this for the uv sent from the vertex shader to the fragment shader.
Konieczne będzie również wycięcie makra TRANSFORM_TEX w module cieniującym wierzchołki, ponieważ oczekuje uv 2D:
// o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.uv = v.uv;
// If you define a float4 with the special name _MainTex_ST,
// you can get the same effect the macro had by doing this:
o.uv.xy = o.uv.xy * _MainTex_ST.xy + _MainTex_ST.zw;
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 :
float2 uv = i.uv.xy / i.uv.z;
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!
id
icount
? Co maUVs.ToArray()
zrobić? Jak przesyłasz na kartę wierzchołki i współrzędne tekstury?