Bagaimana saya bisa memperbaiki artefak pemetaan zig-zagging UV pada mesh yang dihasilkan yang mengecil?


10

Saya membuat mesh prosedural berdasarkan kurva dan ukuran mesh semakin kecil di seluruh kurva seperti yang Anda lihat di bawah ini.

masukkan deskripsi gambar di sini

Dan masalahnya adalah UV akan zig-zag sebagai perubahan ukuran (ini bekerja dengan sempurna ketika ukuran mesh sama di seluruh kurva).

masukkan deskripsi gambar di sini

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

Bagaimana saya bisa memperbaikinya?


Apa iddan count? Apa yang UVs.ToArray()harus dilakukan Bagaimana cara Anda mengunggah koordinat titik dan tekstur ke kartu?
user1118321

@ user1118321 dari konteks, idadalah indeks dari segmen saat ini dari semua bilah di sepanjang strip, di mana ada counttotal. List<T>.ToArray()mengembalikan array yang diketik dari semua entri dalam daftar (jadi di sini, a Vector2[]). Buffer data ini tersedia untuk sistem render dengan menetapkannya ke Meshinstance meshdalam beberapa baris terakhir. Tetapi tidak satu pun dari ini adalah bagian yang sangat menarik dari kode: bagaimana titik titik dipilih. Detail-detail itu akan lebih bermanfaat untuk dilihat. ;)
DMGregory

Itu asumsi saya, tetapi saya meminta klarifikasi karena terkadang asumsi salah. Saya telah melihat sesuatu seperti itu dalam kode saya sendiri di masa lalu hanya untuk menyadari bahwa countsebenarnya berarti simpul, bukan poligon, atau sebaliknya. Memastikan semua yang kita pikir sedang terjadi benar-benar terjadi.
user1118321

Jawaban:


13

Pemetaan UV khas adalah apa yang disebut transformasi affine . Itu berarti pemetaan setiap segitiga antara ruang 3D dan ruang tekstur dapat mencakup rotasi, terjemahan, penskalaan / squash, dan condong (mis. Apa pun yang dapat kita lakukan dengan perkalian matriks homogen)

Hal tentang transformasi affine adalah bahwa mereka seragam di seluruh domain mereka - rotasi, terjemahan, skala, dan condong yang kami terapkan pada tekstur dekat vertex A sama dengan apa yang kami terapkan di dekat vertex B, dalam salah satu segitiga. Garis-garis yang paralel dalam satu ruang akan dipetakan ke garis-garis paralel di ruang lain, tidak pernah konvergen / menyimpang.

Tetapi tapering bertahap yang Anda coba terapkan tidak seragam - memetakan garis paralel dalam tekstur ke garis konvergen pada jala. Itu berarti skala tekstur yang diukur di seluruh band berubah terus-menerus saat kami bergerak ke bawah jalur. Itu lebih dari transformasi affine dari pemetaan UV 2D yang dapat secara akurat mewakili: interpolasi koordinat 2D uv antara simpul yang berdekatan akan mendapatkan satu skala yang konsisten di sepanjang tepi, bahkan tepi diagonal yang harus menyusut dalam skala ketika bergerak ke bawah strip. Ketidakcocokan itu adalah apa yang menciptakan zigzag warbling ini.

Masalah ini muncul kapan saja kami ingin memetakan persegi panjang ke trapesium - sisi paralel ke sisi konvergen: tidak ada transformasi affine yang melakukan ini, jadi kami harus memperkirakannya sedikit demi sedikit, yang mengarah ke jahitan yang terlihat.

Untuk sebagian besar tujuan, Anda dapat meminimalkan efek dengan menambahkan lebih banyak geometri. Menambah jumlah subdivisi sepanjang panjang strip, dan membelah strip menjadi dua atau lebih segmen sepanjang lebarnya, dengan diagonal segitiga yang diatur dalam pola herringbone, dapat membuat efeknya kurang terlihat. Akan selalu ada sampai batas tertentu selama kita menggunakan transformasi affine.

Tapi ada jalan lain. Kita dapat menggunakan trik yang sama yang kita gunakan untuk rendering 3D untuk menggambar trapesium dalam perspektif yang diberikan dinding & lantai persegi panjang: kita menggunakan koordinat proyektif !

Affine texturing: Contoh tekstur textine normal dengan artefak zig-zag

Tekstur projektif: Contoh proyeksi textring yang mengoreksi artefak

Untuk melakukan ini, kita perlu menambahkan koordinat uv ketiga (uvw) dan memodifikasi shader kita.

Diberikan faktor skala pada setiap titik (katakanlah, sama dengan luas strip Anda di tempat itu), Anda dapat membuat koordinat 3D proyektif uvw dari koordinat 2D uv biasa dengan cara ini:

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

Untuk menerapkan koordinat 3D uvw ini ke mesh Anda, Anda harus menggunakan Vector3 overload Mesh. SetUVs (saluran int, List uvs)

Dan pastikan untuk mengubah struct input shader Anda untuk mengharapkan koordinat tekstur 3D (ditampilkan di sini menggunakan shader unlit default):

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.

Anda juga harus memotong makro TRANSFORM_TEX di vertex shader, karena mengharapkan 2D uv:

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

Akhirnya, untuk kembali ke koordinat tekstur 2D untuk pengambilan sampel tekstur, Anda hanya membaginya dengan koordinat ketiga dalam shader fragmen Anda :

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

Karena kami membuat koordinat uvw 3D ini dari koordinat 2D yang dikehendaki dengan mengalikannya dengan angka yang sama, kedua operasi dibatalkan dan kami kembali ke koordinat 2D yang dikehendaki, tetapi sekarang dengan interpolasi non-linear antar simpul. : D

Sangat penting untuk melakukan pembagian ini per fragmen dan tidak di vertex shader. Jika dilakukan per titik, maka kita kembali menginterpolasi koordinat yang dihasilkan secara linier di setiap sisi, dan kami telah kehilangan nonlinier yang kami coba perkenalkan dengan koordinat proyektif!


Hai, saya sudah bergumul dengan masalah yang sama untuk beberapa waktu sekarang, dan sepertinya inilah yang terjadi pada saya. Satu-satunya perbedaan adalah bahwa saya bekerja di threejs dan bukan dalam kesatuan. Kami berhasil memecahkan masalah dengan meningkatkan jumlah segitiga, tetapi masih ingin mencoba tekstur projektif. Apakah Anda tahu bagaimana memulai menerapkan ini di threejs? Terima kasih!
Dživo Jelić

1
Hampir sama caranya. Anda perlu koordinat tekstur ketiga untuk menyimpan pembagi, kemudian Anda melakukan pembagian dalam shader fragmen. Jika Anda kesulitan menerapkan ini pada kasus Anda, mengajukan pertanyaan baru akan memungkinkan Anda memasukkan sampel kode, menunjukkan bagaimana Anda menggambar mesh Anda sejauh ini, yang bisa dijadikan jawaban.
DMGregory

Apakah saya perlu menyimpan pembagi sebagai koordinat ketiga (dan karena itu mengubah struct dan memotong makro TRANSFORM_TEX, yang saya tidak tahu bagaimana melakukannya dalam threejs) atau dapatkah saya meneruskan pembagi sebagai atribut untuk vertex shader dan kemudian dari sana sebagai variasi ke fragmen shader di mana itu bisa digunakan untuk divisi?
Dživo Jelić

TRANSFORM_TEX adalah makro Persatuan. Anda tidak memilikinya dalam tiga. Jadi, tidak ada yang cocok. Selama koordinat dan pembagi terinterpolasi mencapai shader fragmen, tidak masalah bagaimana Anda mendapatkannya di sana. Apakah Anda mengalami kesulitan menyediakannya sebagai atribut / bervariasi sejauh ini?
DMGregory

Saya belum mencoba karena saya tidak ingin membuang waktu sampai saya memverifikasi bahwa itu mungkin. Hanya satu pertanyaan terakhir, pembagi juga akan diinterpolasi begitu mencapai fragmen shader, benar? Berarti pada pixel antara dua simpul akan ada nilai interpolasi dan bukan nilai asli? Saya kesulitan membungkus kepala saya mengapa mengalikan UV dan kemudian membaginya membantu, tapi saya akan mengambil kata-kata Anda untuk itu dan mencobanya. : sedikit_smiling_face: Terima kasih banyak atas bantuan Anda!
Dživo Jelić
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.