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.
Jawaban:
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
textureLod
untuk 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
dFdx
dandFdy
pada UVs, yang memiliki diskontinuitas karenaatan2
, Anda bisa menerapkandFdx
dandFdy
untukfragVert
(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.
sumber