Tekstur mengkoordinasikan diskontinuitas dengan mipmaps menciptakan jahitan

9

Saya baru saja mulai belajar openGL dan saya mendapatkan artefak ini saat membuat tekstur bola dengan mipmaps. Pada dasarnya ketika fragmen sampel tepi tekstur saya, ia mendeteksi diskontinuitas (katakanlah dari 1 hingga 0) dan memilih mipmap terkecil, yang menciptakan jahitan jelek ini:

jahitan jelek http://cdn.imghack.se/images/6bbe0ad0173cac003cd5dddccbdbdbdc7.png

Jadi saya mencoba untuk secara manual menimpa gradien dengan menggunakan teksturGrad:

//fragVert is the original vertex from the vertex shader
vec2 ll = vec2((atan(fragVert.y, fragVert.x) / 3.1415926 + 1.0) * 0.5, (asin(fragVert.z) / 3.1415926 + 0.5));
vec2 ll2 = ll;
if (ll.x < 0.01 || ll.x > 0.99)
    ll2.x = .5;
vec4 surfaceColor = textureGrad(material.tex, ll, dFdx(ll2), dFdy(ll2));

Sekarang saya mendapatkan dua jahitan, bukan satu. Bagaimana saya bisa menyingkirkan mereka? Dan mengapa kode di atas menghasilkan 2 jahitan?

2 eams http://cdn.imghack.se/images/44a38ef13cc2cdd801967c9223fdd2d3.png

Anda tidak bisa membedakan kedua gambar tetapi kedua jahitannya berada di kedua sisi jahitan asli.

omikun
sumber
2
Apakah bola Anda sebuah jaring, atau apakah Anda raytracing bola secara analitik di shader atau sejenisnya? Jika itu adalah mesh, orang biasanya menyelesaikan ini dengan menduplikasi simpul sepanjang jahitan sehingga verts di satu sisi dapat memiliki u = 0 dan sisi lain memiliki u = 1.
Nathan Reed
Adapun mengapa kode Anda menghasilkan dua jahitan, saya berharap itu karena itu menciptakan dua diskontinuitas - satu di mana Anda melompat dari 0,01 ke 0,5, dan satu di mana Anda melompat dari 0,99 ke 0,5. Ini masalah yang sama seperti ketika Anda melompat dari 0 ke 1 - tidak sebesar lompatan tetapi masih lompatan besar.
Nathan Reed
Saya memiliki mesh untuk bola. Ini adalah decahedron sehingga simpul tidak sejajar dengan jahitan. Yang lucu dari kedua jahitan itu adalah jahitan aslinya hilang. Juga, saya mendapatkan 2 jahitan yang sama bahkan jika saya menjepitnya menjadi 0,01 atau 0,99.
omikun
Bisakah Anda memposting tangkapan layar dari kasus dua jahitan? Dan, bagaimana Anda menghasilkan UV (dapatkah Anda memposting bagian yang relevan dari kode Anda)? Saya kira Anda membuat mereka secara prosedural dalam shader, tidak hanya interpolasi mereka dari simpul, kalau tidak mesh dodecahedron Anda tidak akan bekerja sama sekali.
Nathan Reed
Saya memperbarui pertanyaan dengan gambar kedua jahitannya, kedua sisi jahitan asli, tetapi jahitan asli tidak ada. Saya pikir UV diinterpolasi dari simpul, tidak yakin. Kode tersebut ada dalam pertanyaan sekarang.
omikun

Jawaban:

4

Berdasarkan kode shader yang Anda poskan, Anda tidak menginterpolasi UV dari simpul - tetapi tampaknya Anda menginterpolasi posisi 3D ( fragVert), lalu menghitung UV dengan mentransformasikannya ke koordinat bola.

Analisis Anda benar karena mipmap terkecil dipilih ketika ada diskontinuitas, karena pemilihan mipmap didasarkan pada turunan yang diperkirakan secara numerik dari UV yang digunakan dalam piksel tetangga. Ketika satu pixel memiliki u = 0 dan yang lainnya memiliki u = 1 Anda mendapatkan turunan yang sangat besar. Upaya perbaikan Anda memiliki masalah yang sama dengan turunan besar terjadi di sekitar u = 0,01 dan u = 0,99, itulah sebabnya dua jahitan muncul di kedua sisi di mana jahitan asli berada.

Pendekatan yang relatif sederhana untuk memperbaiki masalah adalah memutuskan level mip mana yang akan digunakan sendiri dan menelepon textureLoduntuk mengambil sampel secara langsung. Jika planet ini selalu akan cukup dekat dengan kamera, Anda bisa mengubah kode level mip menjadi 0 (atau, dalam hal ini, sama sekali tidak menyertakan level mip dalam tekstur). Kalau tidak, itu bisa didasarkan pada log2 jarak titik dari kamera, diskalakan oleh beberapa faktor yang sesuai. Perhatikan bahwa ini akan secara efektif menonaktifkan penyaringan anisotropik.

Pendekatan yang lebih "benar" adalah menghitung beberapa derivatif berkualitas lebih tinggi. Alih-alih menggunakan dFdxdan dFdypada UVs, yang memiliki diskontinuitas karena atan2, Anda bisa menerapkan dFdxdan dFdyuntuk fragVert(yang akan terus menerus sepanjang jalan di sekitar bola), kemudian menggunakan beberapa kalkulus (chain rule) untuk menemukan formula untuk mendapatkan turunan UV dari posisi derivatif. Ini akan lebih rumit dan lebih lambat, tetapi memiliki keuntungan bahwa penyaringan anisotropik harus bekerja.

Akhirnya, karena Anda baru di OpenGL, saya hanya akan mencatat bahwa sementara menghitung UV dari koordinat bola adalah cara yang benar-benar valid untuk tekstur bola, itu bukan cara "biasa" yang dipilih kebanyakan orang. Ini lebih umum untuk membangun sphere mesh yang memiliki UV yang ditentukan per vertex, dan hanya diteruskan dari vertex shader ke pixel shader (diinterpolasi secara linear di setiap segitiga). Verteks ditempatkan di sepanjang jahitan, seperti ini , sehingga ada dua salinan dari setiap simpul, pada posisi yang persis sama, tetapi setengah dengan u = 0 terhubung ke segitiga di satu sisi, dan setengah lainnya dengan u = 1 terhubung ke segitiga di sisi lain. Ini menghilangkan semua jahitan yang terlihat dan tidak memerlukan trik dalam pixel shader.

Nathan Reed
sumber