Zig-zagging UV haritalama artefaktlarını, incelen bir ağ üzerinde nasıl düzeltebilirim?


10

Bir eğriye dayalı yordamsal bir kafes oluşturuyorum ve kafesin boyutu aşağıda gördüğünüz gibi eğri boyunca küçülüyor.

resim açıklamasını buraya girin

Ve sorun, boyut değiştikçe UV'nin zikzaklı hale gelmesidir (ağın boyutu eğri boyunca aynı olduğunda mükemmel çalışır).

resim açıklamasını buraya girin

 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();

Bunu nasıl düzeltebilirim?


Nedir idve count? Ne yapar UVs.ToArray()? Köşeleri ve doku koordinatlarını karta nasıl yüklüyorsunuz?
user1118321

@ user1118321 bağlamdan, idtoplam segmentin bulunduğu şerit boyunca tüm çapraz çubuklardan geçerli segmentin dizinidir count. List<T>.ToArray()listedeki tüm girdilerin yazılı bir dizisini döndürür (burada, a Vector2[]). Bu veri arabellekleri , son birkaç satırdaki Meshörneğe atanarak oluşturma sistemine sunulur mesh. Ancak bunların hiçbiri kodun özellikle ilginç kısmı değildir: tepe noktalarının nasıl seçildiği. Bu ayrıntıları görmek daha yararlı olacaktır. ;)
DMGregory

Bu benim varsayımımdı, ama açıklamayı istedim çünkü bazen varsayımlar yanlış. Geçmişte kendi kodumda böyle bir şeye baktım, sadece countbunun çokgenler yerine köşeler anlamına geldiğini fark ettim , ya da tam tersi. Sadece düşündüğümüz her şeyin devam ettiğinden emin olmak.
user1118321

Yanıtlar:


13

Tipik UV haritalaması afin dönüşüm olarak adlandırılan şeydir . Bu, 3D alan ve doku alanı arasındaki her üçgenin eşleşmesinin rotasyon, çeviri, ölçeklendirme / squash ve eğrilmeyi (yani homojen bir matris çarpımı ile yapabileceğimiz her şeyi) içerebileceği anlamına gelir.

Afin dönüşümlerle ilgili olan şey , tüm alan adlarında tek biçimli olmalarıdır - A köşesi yakınındaki dokuya uyguladığımız rotasyon, çeviri, ölçek ve eğim, herhangi bir üçgen içinde B köşesine yakın uyguladığımızla aynıdır. Bir boşlukta paralel olan çizgiler diğerinde paralel çizgilerle eşleştirilir, asla yakınsama / ayrılma olmaz.

Ancak uygulamaya çalıştığınız kademeli koniklik düzgün değildir - dokudaki paralel çizgileri kafes üzerindeki yakınsak çizgilere eşler. Bu, şeridi aşağı doğru hareket ettirdikçe bant boyunca ölçülen doku ölçeğinin sürekli değiştiği anlamına gelir. Bu, 2D UV eşlemenin afin dönüşümlerinin doğru bir şekilde temsil edebileceğinden daha fazlasıdır: bitişik köşeler arasında enterpolasyonlu 2D uv koordinatları, tüm kenar boyunca bir tutarlı ölçek elde eder, hatta şerit aşağı doğru ilerledikçe ölçek küçülmesi gereken çapraz kenar. Bu uyuşuk zikzak yaratan şey bu uyumsuzluktur.

Bu sorun, bir dikdörtgeni yamuk - paralel taraflarla yakın taraflara eşlemek istediğimiz zaman ortaya çıkıyor: Bunu yapan sadece afin dönüşüm yok, bu yüzden parçalı olarak yaklaşık dikişler yapmalıyız ve görünür dikişlere yol açmalıyız.

Çoğu amaç için daha fazla geometri ekleyerek efekti en aza indirebilirsiniz. Şeridin uzunluğu boyunca alt bölümlerin sayısını arttırmak ve şeridi genişliği bir balıksırtı deseninde düzenlenmiş üçgenlerin köşegenleri ile iki veya daha fazla parçaya bölmek, etkiyi daha az fark edilir hale getirebilir. Afin dönüşümleri kullandığımız sürece her zaman bir dereceye kadar mevcut olacaktır.

Ama etrafında bir yol var. Biz perspektif verilen dikdörtgen duvarlar ve zeminler yamuklarını çizmek render biz 3D için kullanmak aynı numarayı kullanabilirsiniz: Kullandığımız yansıtmalı koordinatları !

Afin dokular: Zig-zag artefaktlarıyla normal afin doku örneği

Projektif tekstüre etme: Artefaktları düzelten projektif metin örneği

Bunu yapmak için üçüncü bir uv koordinatı (uvw) eklememiz ve gölgelendiricilerimizi değiştirmemiz gerekir.

Her bir noktada bir ölçek faktörü göz önüne alındığında (örneğin, o noktadaki şeridinizin genişliğine eşit), 3D projektif uvw koordinatını normal 2D uv koordinatınızdan şu şekilde oluşturabilirsiniz:

Vector3 uv3 = ((Vector3)uv2) * scale;
uv3.z = scale;

Bu 3B uvw koordinatlarını ağınıza uygulamak için Vector3 aşırı yük Mesh'i kullanmanız gerekir. SetUV'ler (int kanal, Liste uvs)

Ayrıca, 3B doku koordinatı (burada varsayılan ışıksız gölgelendirici kullanılarak gösterilmiştir) beklemek için gölgelendiricinizin giriş yapısını değiştirdiğinizden emin olun:

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.

Ayrıca bir 2D uv beklediğinden köşe gölgeleyicisinde TRANSFORM_TEX makrosunu kesmeniz gerekir:

// 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;

Son olarak, doku örneklemesi için bir 2B doku koordinatına geri dönmek için, sadece parça gölgelendiricinizdeki üçüncü koordinatla bölünürsünüz :

float2 uv = i.uv.xy / i.uv.z;

Bu 3B uvw koordinatını aynı sayı ile çarparak istenen 2D koordinatımızdan yaptığımız için, iki işlem iptal edilir ve istenen orijinal 2D koordinatımıza geri döneriz, ancak şimdi köşeler arasında doğrusal olmayan enterpolasyonla. : D

Bu bölmeyi köşe gölgeleyicisinde değil, parça başına yapmak önemlidir. Köşe başına yapılırsa, sonuçta ortaya çıkan koordinatları her kenar boyunca doğrusal olarak enterpolasyona geri döndürüyoruz ve projektif koordinatla tanıtmaya çalıştığımız doğrusal olmayanlığı kaybettik!


Merhaba, uzun süredir aynı sorunla mücadele ediyorum ve bu tam olarak başıma gelen gibi görünüyor. Tek fark şu ki, birlikte değil üç dj'de çalışıyorum. Sorunu üçgen sayısını artırarak çözmeyi başardık, ancak yine de projektif dokulamayı denemek istiyoruz. Bunu threejs'de uygulamaya nasıl başlayacağınız hakkında bir fikriniz var mı? Teşekkür ederim!
Dživo Jelić

1
Hemen hemen aynı şekilde. Böleni saklamak için üçüncü bir doku koordinatına ihtiyacınız vardır, daha sonra bölümü parça gölgelendiricide gerçekleştirirsiniz. Bunu davanıza uygulamakta sorun yaşıyorsanız, yeni bir soru sormak, şu ana kadar ağınızı nasıl çizdiğinizi gösteren bir kod örneği eklemenize izin verecektir, bu cevaplar üzerine inşa edilebilir.
DMGregory

Bölücüyü üçüncü bir koordinat olarak saklamam gerekiyor mu (ve bu değişiklik yapısı nedeniyle ve üç js'de nasıl yapacağımı bilmediğim TRANSFORM_TEX makrosunu kestiğim) veya bölücüyü köşe gölgelendiriciye bir özellik olarak geçirebilir miyim? ve sonra bölüme alışabileceği parça gölgelendiriciye varyasyonlar olarak?
Dživo Jelić

TRANSFORM_TEX bir Birlik makrosudur. Three.js'de buna sahip değilsiniz, bu yüzden kesilecek bir şey yok. Enterpolasyonlu uv koordinatları ve bölücüler parça gölgelendiriciye ulaştığı sürece, onları oraya nasıl getirdiğiniz önemli değildir. Şu ana kadar bir özellik / değişkenlik sağlama konusunda herhangi bir sorunla karşılaştınız mı?
DMGregory

Henüz mümkün olmadığını doğrulayana kadar zaman kaybetmek istemediğim için denemedim. Son bir soru, bölen de parça gölgelendiriciye ulaştığında enterpolasyona girecek, değil mi? İki köşe arasındaki pikselde, orijinal değer değil, enterpolasyonlu bir değer olacağı anlamına mı geliyor? Neden UV'yi çarpıp sonra bölmek yardımcı oluyor diye kafamı sarmakta zorlanıyorum, ama sözünü alıp deneyeceğim. : little_smiling_face: Yardımınız için çok teşekkür ederim!
Dživo Jelić
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.