Three.js: Normalnya membalik beberapa bagian jaring yang memiliki bahan bersisi ganda

Dibuat pada 23 Okt 2019  ·  36Komentar  ·  Sumber: mrdoob/three.js

Deskripsi masalah

Mengupgrade dari 107 ke 108, saya perhatikan bahwa bagian dari model saya sekarang terlihat seperti telah membalik normal. Ini hanya terjadi dengan bahan bersisi ganda.
Lihat di sini: https://vaulted-jonquil.glitch.me/

Seperti inilah seharusnya, dengan pola yang menjorok di kedua roda. Begitulah di 107
Screen Shot 2019-10-23 at 3 51 35 PM

Dalam 108 meskipun salah satu roda memiliki pola yang terlihat seperti menyembul:
Screen Shot 2019-10-23 at 3 51 27 PM

Versi Three.js
  • [x] r108
Browser
  • [x] Semuanya
OS
  • [x] Semuanya
  • [] Jendela
  • [] macOS
  • [] Linux
  • [] Android
  • [] iOS
Bug Regression

Komentar yang paling membantu

Perbaiki!
Screen Shot 2019-11-21 at 10 02 54 AM

Semua 36 komentar

@ Pushmatrix Dapatkah Anda mengonfirmasi apakah model ini menyediakan atau tidak menyediakan garis singgung sendiri? Saya ingin tahu apakah ini mungkin terkait dengan # 11438.

Saya tidak percaya itu menentukan garis singgung sendiri

Menggunakan kasus uji yang berbeda, git bisect menunjuk ke # 17586 sebagai PR yang memulai masalah jika mesh bersisi ganda dan memiliki skala negatif X. Itu berada di r.109, bukan r.108, namun.

Ini tidak diuji pada model dari PR ini karena model itu tidak tersedia.

Berikut tes glb
wheels.glb.zip

Dari 3 tahun yang lalu: https://github.com/mrdoob/three.js/issues/10331#issue -194807426

Pada dasarnya sepertinya ... gl_FrontFace tidak berfungsi dengan baik dengan material dua sisi pada GPU Adreno.

Apakah ini _masih_ masalah yang perlu kita atasi?

//

Model ini tampaknya dirender dengan benar di komputer saya jika kami menghapus solusi Adreno di normalmap_pars_fragment :

#ifdef DOUBLE_SIDED

    // Workaround for Adreno GPUs gl_FrontFacing bug. See #15850 and #10331

    bool frontFacing = dot( cross( S, T ), N ) > 0.0;

    mapN.xy *= ( float( frontFacing ) * 2.0 - 1.0 );

#else

    mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );

#endif

Hmm, saya juga ingat pernah membaca komentar itu; Saya rasa saya menemukannya saat melihat bug ini, yang tampaknya telah diperbaiki di r108 (setidaknya peningkatan versi memperbaikinya untuk kami): https://github.com/GoogleWebComponents/model-viewer/issues/740

Mungkin itu terkait? FWIW, saya mendapat beberapa tanggapan tentang GPU Adreno lama, jadi tampaknya mereka masih cukup umum.

Sekadar konfirmasi, ini masih terjadi di dev :

Screen Shot 2019-10-25 at 4 06 51 PM

Sekadar konfirmasi, ini masih terjadi di dev:

Baik. Tetapi tidak jika Anda menghapus solusi bug Adreno.

Tetapi tidak jika Anda menghapus solusi bug Adreno.

Bagaimana jika menghapus solusi untuk saat ini dan kemudian mencari solusi yang berbeda? Penerapan saat ini menyebabkan visual yang salah, apa pun platform yang Anda gunakan.

@ Mugen87 Dalam kasus khusus ini, saya percaya geometri adalah cermin satu sama lain, tetapi mereka berbagi peta normal yang sama.

Saya setuju dengan kamu. Saya telah menginvestasikan berjam-jam mencoba untuk menemukan solusi yang kompatibel dengan Adreno yang benar dalam setiap kasus penggunaan.

Memeriksa model model roda, setiap roda memiliki selubung UV sendiri. Itu tidak berbagi satu pun.
Dan urutan puncaknya berlawanan.

Namun orientasi wajahnya sama, setidaknya di Blender.

Screen Shot 2019-11-18 at 11 21 05 AM

Jadi saya tidak yakin apakah itu bug di r108, ​​atau apakah r108 sekarang melakukan sesuatu dengan benar. ¯_ (ツ) _ / ¯

@pushmatrix dapatkah Anda membandingkan dengan Unity atau Blender?

@tokopedia

Blender 2.8

Screen Shot 2019-11-20 at 8 27 27 AM

Kesatuan

Screen Shot 2019-11-20 at 8 40 30 AM

Sketchfab

Screen Shot 2019-11-20 at 8 32 48 AM

@bayu_joo

Unity sulit dilihat karena cahayanya searah dengan kamera, tetapi sepertinya Unity juga salah? 🤔

@tokopedia

Ya itu memang tergantung sedikit pada pencahayaan, itu akhirnya menjadi ilusi dan terlihat seperti itu muncul di beberapa tempat. Tetapi ketika Anda memutar, itu menghilang.

Ini dia dalam cahaya lain, yang tampak benar
Screen Shot 2019-11-20 at 2 36 16 PM

@mrdoob Muka depan memiliki urutan pemutaran berlawanan arah jarum jam di three.js. Biasanya, UV dari 3 simpul dari masing-masing permukaan juga memiliki urutan belitan berlawanan arah jarum jam pada peta UV.

Dalam contoh ini, _conjecture_ saya adalah model di sebelah kiri memiliki UV berlawanan arah jarum jam dan model di sebelah kanan memiliki UV _clockwise_. Model di sebelah kanan dirender secara tidak benar di three.js ketika doubleSide adalah true .

AFAIK, menghapus solusi Adreno akan memperbaiki masalah untuk GPU non-Adreno.

@pushmatrix Contoh Unity Anda tampaknya memiliki lampu terarah dari dua arah. Itu membuatnya sulit untuk membedakan apa yang sedang terjadi. Lampu tunggal mungkin lebih disukai.

@WestLangley Saya menggunakan peta lingkungan yang sama dengan model-viewer yang digunakan, tetapi kemungkinan besar tidak memiliki rotasi yang sama. Saya akan mencoba dengan satu lampu.

@WestLangley Lampu satu arah berputar ke sekeliling. Saya merasa seperti sedang melihat ilusi optik

unity

Sepertinya Unity membuat alur masuk dan keluar tergantung pada bagaimana cahaya menerpa, tapi setidaknya konsisten untuk keduanya.

Threejs juga konsisten, tetapi yang pasti terlihat selalu muncul:
wheels

Saya merasa ada yang salah di Unity one ...
Seperti itu membutuhkan sesuatu seperti. material.normalMapScale.x = -1 .

@WestLang

@mrdoob Muka depan memiliki urutan pemutaran berlawanan arah jarum jam di three.js. Biasanya, UV dari 3 simpul dari masing-masing permukaan juga memiliki urutan belitan berlawanan arah jarum jam pada peta UV.

Dalam contoh ini, _conjecture_ saya adalah model di sebelah kiri memiliki UV berlawanan arah jarum jam dan model di sebelah kanan memiliki UV _clockwise_. Model di sebelah kanan dirender secara tidak benar di three.js ketika doubleSide adalah true .

AFAIK, menghapus solusi Adreno akan memperbaiki masalah untuk GPU non-Adreno.

Terima kasih, itu masuk akal. Saya pikir itu masih perlu penyelidikan lebih lanjut. Jika Sketchfab terlihat benar di semua perangkat, kami mungkin harus melihat shadernya.

Saya telah melihat kode shader masing-masing hari ini dan tampaknya mereka tidak menggunakan "Per-Pixel Tangent Space Normal Mapping".

Menurut postingan ini, Sketchfab mengharapkan definisi tangen pada aset atau data tersebut
menghasilkan berdasarkan koordinat uv. Itu sesuai dengan apa yang saya lihat di kode GLSL.

Jika saya menambahkan garis singgung ke model melalui BufferGeometryUtils.computeTangents() dan menetapkan Material.vertexTangents menjadi true , hasilnya tampak baik-baik saja:

image

BTW: Bolehkah membagikan cuplikan kode dari Sketchfab di postingan ini ^^? Bagaimanapun, ini bukan open-source.

Untuk konsistensi, inilah Sketchfab dengan 1 lampu arah yang bergerak maju mundur:

sketchfab

Ya, satu hal yang perlu diingat adalah Sketchfab memang melakukan pemrosesan saat Anda mengupload model, jadi kemungkinan besar mereka dapat menghasilkan sesuatu / mengubah sesuatu. Apa yang Anda lihat bukanlah glTF tetapi file glTF yang dikonversi ke formatnya sendiri.

@pushmatrix Dapatkah Anda _please_ mendemonstrasikan bahwa # 17958 berfungsi untuk model Anda?

three.js menghitung garis singgung di shader fragmen. Saya yakin ini berfungsi dengan benar jika peretasan untuk mengakomodasi GPU Adreno buggy tertentu dihapus. Lihat # 17958.

//

Sketchfab menghitung garis singgung pada CPU saat garis singgung diperlukan dan tidak disediakan oleh model. ( @donmccurdy Inilah yang dibutuhkan spesifikasi glTF.)

three.js juga dapat melakukannya, tetapi itu berarti menambahkan garis singgung yang benar ke semua geometri bawaan. three.js juga harus mengimplementasikan algoritma MIKKTSpace untuk menggantikan ComputeTangents() . Karena three.js mendukung geometri yang diindeks dan tidak diindeks, saya berharap ini akan membutuhkan banyak usaha.

Perbaiki!
Screen Shot 2019-11-21 at 10 02 54 AM

Oke, jadi sepertinya solusi di sini adalah mengembalikan solusi Adreno (# 17958) dan merekomendasikan orang untuk menggunakan BufferGeometryUtils.computeTangents() ketika model tidak memiliki garis singgung dan mereka bertujuan untuk mendukung GPU Adreno (# 15850) .

Kedengarannya bagus?

Solusi lain adalah memanggil BufferGeometryUtils.computeTangents() di mesin secara otomatis ketika tidak tersedia dan menghapus semua kode yang menghitung tangen di shader fragmen ... 🤔

BufferGeometryUtils.computeTangents() saat ini membutuhkan indeks sehingga tidak dapat digunakan di inti. Namun, saya pikir akan lebih baik jika three.js dapat menghasilkan garis singgung menurut MIKKTSpace di beberapa titik dan kemudian menghapus perturbNormal2Arb() .

@WestLangley menulis:

itu berarti menambahkan garis singgung yang benar ke semua geometri built-in.

Berubah pikiran ... Garis singgung tidak selalu diperlukan. Sebagai gantinya, saya akan mengembalikan metode BufferGeometry.computeTangents() dan "menimpa" metode itu untuk semua geometri built-in yang kita dapat mengatur garis singgung yang tepat secara analitis.

//

Solusi lain adalah memanggil BufferGeometryUtils.computeTangents () di mesin secara otomatis ketika tidak tersedia dan menghapus semua kode yang menghitung tangen di shader fragmen ...

Kedengarannya benar bagi saya.

BufferGeometryUtils.computeTangents () saat ini memerlukan indeks sehingga tidak dapat digunakan di inti.

Saya pikir itu mudah diperbaiki. Dan itu harus diperbaiki untuk mendukung https://github.com/mrdoob/three.js/issues/17804#issuecomment -557135610.

akan lebih baik jika three.js dapat menghasilkan garis singgung menurut MIKKTSpace di beberapa titik dan kemudian menghapus perturbNormal2Arb () ...

Saya tidak tahu apakah MikkTSpace harus mengganti komputasi shader fragmen. Shader hampir tidak memiliki biaya kinerja, dan berfungsi dengan baik untuk sebagian besar model. Prekomputasi garis singgung memiliki biaya dimuka per-vertex setiap saat, dan tidak ada manfaat kecuali dalam kasus khusus ini. 😕 Terlepas dari apa yang dikatakan spesifikasi glTF, saya mengalami kesulitan membenarkan melakukan itu secara default.

Alangkah baiknya jika BufferGeometryUtils.computeTangents dapat mengimplementasikan pendekatan MikkTSpace - itu adalah algoritma terbaik, jika Anda harus menghitungnya terlebih dahulu. Tetapi mungkin akan lebih mudah untuk meletakkan MikkTSpace di alat seperti glTF-Pipeline atau gltfpack, yang dapat menggunakan implementasi asli yang sudah ada, dan melakukan penghitungan sebelumnya, secara offline.

@tokopedia

Tetapi, katakanlah ... dalam kasus penggunaan <model-viewer> , saya rasa tidak ada cara yang dapat diandalkan untuk mengetahui apakah pengguna memiliki GPU Adreno tetapi kami ingin terlihat benar (https: // github. com / GoogleWebComponents / model-viewer / issues / 740).

Haruskah <model-viewer> (dan proyek lain yang membutuhkan dukungan x-gpu) harus memanggil BufferGeometryUtils.computeTangents ketika garis singgung tidak tersedia, atau haruskah Three?

@bayu_joo

Haha, saya baru menyadari dari mana roda ini berasal 😁

https://bumbleride.com/products/era?variant=20719969599599

Screen Shot 2019-11-22 at 3 52 19 PM

@mrdoob 🕵

Oke, mari kembalikan solusi untuk saat ini.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat