Three.js: Pencahayaan selektif

Dibuat pada 10 Agu 2014  ·  101Komentar  ·  Sumber: mrdoob/three.js

Saya tidak yakin apakah ini sudah merupakan fitur yang direncanakan atau mungkin bahkan sudah selesai, jadi saya akan mencoba menjelaskan tugasnya terlebih dahulu.

Saya perlu melakukan pencahayaan selektif untuk ruangan yang berbeda. Sebagai contoh, saya memiliki dua kamar. Satu cahaya hanya boleh memengaruhi objek dan dinding bagian dalam satu ruangan. Ruangan kedua tidak boleh terpengaruh oleh cahaya ini.

Saat ini, jika saya menambahkan cahaya ke pemandangan, itu mempengaruhi semua objek di kejauhan. Dan saya mendapatkan efek aneh ketika cahaya datang "melalui dinding" kamar kedua.

Jadi saya rasa saya membutuhkan semacam grup atau saluran untuk penerangan, sehingga saya dapat mengatur objek yang dipengaruhi oleh satu sumber cahaya dan objek yang dipengaruhi oleh sumber cahaya lainnya.

Saya belum menemukan hal seperti itu baik di lampu atau objek, jadi saya pikir mungkin itu bisa menjadi fitur yang bagus untuk dimiliki.

Dan, btw, jika belum diimplementasikan, apa pendekatan yang disarankan untuk menyelesaikan tugas seperti itu menggunakan status three.js saat ini?

Enhancement

Komentar yang paling membantu

Apakah Anda memiliki tautan ke contoh sesuatu seperti ini?

di sini, saya membuat satu hanya untuk Anda: https://jsfiddle.net/f2Lommf5/524/

Semua 101 komentar

Apa yang saya katakan pada dasarnya adalah memiliki bidang channel di THREE.Light dan lightChannel bidang di THREE.Mesh atau sesuatu seperti itu. Jika yang terakhir adalah nol maka itu dipengaruhi oleh semua sumber cahaya. Jika yang terakhir tidak nol maka hanya terpengaruh saluran cahaya dengan nilai yang sama.

Atau mungkin bisa ditambahkan bukan ke Mesh itu sendiri, tapi untuk memisahkan wajah geometri mesh.

Kedengarannya seperti Anda ingin menggunakan bayangan?

Yah, saya bisa mencapai sesuatu seperti itu dengan bayangan (dan saya sudah mencoba), tetapi itu memberikan efek samping yang berbeda dan saya merasa itu adalah peretasan, karena saya tidak perlu menyalakan beberapa objek dan kemudian membayangi mereka . Saya tidak harus menyalakan mereka di tempat pertama.

Yang saya butuhkan adalah bahwa sumber cahaya tertentu tidak mempengaruhi satu set jerat, tetapi mempengaruhi set lainnya.

Biasanya saya melakukan ini dengan menggunakan teknik seperti itu: Contoh utas diskusi :

glEnable(GL_LIGHT0);
//...
glEnable(GL_LIGHTn);

// Draw the walls to room 1
DrawWalls(room[0]);

// Draw the contents of room 1
DrawContents(room[0]);

glDisable(GL_LIGHT0);
//...
glDisable(GL_LIGHTn);

// Draw the walls to room 2
DrawWalls(room[1]);

// Draw the contents of room 2
DrawContents(room[1]);

Jadi sepertinya fitur yang berbeda dari sekedar bayangan. Atau apakah saya melewatkan sesuatu?

Ya... Saya pikir ini memang berguna. Tidak yakin bagaimana tampilan API untuk itu.

Mungkin solusi paling sederhana bisa menjadi yang paling efektif di sini:

  1. Tambahkan channel (atau group ) ke THREE.Light
  2. Tambahkan affectedByLightChannel (atau affectedByLightGroup ) ke THREE.Mesh (Atau mungkin bahkan ke wajah dalam geometri)

Bagaimana menurut anda?

Mungkin 'affectedByLightChannel' terlalu panjang dan sesuatu seperti 'lightChannel' bisa digunakan, tapi saya pikir akan lebih mudah: hanya nomor saluran pada sumber cahaya dan receiver.

Seperti itu:

    light = new THREE.PointLight(0xFFF7D6, 1.0, 15)
    light.channel = 123
    testScene.add(light)

    testScene = new THREE.Scene
    geometry = new THREE.BoxGeometry(2,2,2)
    material = new THREE.MeshLambertMaterial 
        color: 0xffffff

    cube = new THREE.Mesh(geometry, material)
    cube.lightChannel = 123
    testScene.add(cube)

Jika lightChannel sama dengan 0, maka itu dipengaruhi oleh semua saluran. Jika channel sama dengan 0, maka itu mempengaruhi semua mesh.

Jadi itu akan sepenuhnya kompatibel dengan perilaku saat ini.

Itu mungkin agak terlalu sulit untuk dipahami ... Mungkin lebih baik seperti ini:

cube.lightInfluences = [ light1, light2 ];

Tampaknya baik-baik saja bagi saya.

Mungkin sedikit lebih sulit untuk digunakan dalam beberapa kasus, tetapi jelas lebih mudah untuk dipahami.

Bagaimana dengan properti topeng bilangan bulat sederhana untuk jerat dan lampu?

light = new THREE.PointLight(0xFFF7D6, 1.0, 15)
light.mask = 0xffffffff; // default mask
testScene.add(light);

cube = new THREE.Mesh(geometry, material)
cube.mask = 0xffffffff; // default
testScene.add(cube);

Objek kemudian hanya diterangi oleh lampu jika logika AND dari topengnya bukan nol.
Ini akan memungkinkan lampu dipengaruhi oleh lebih dari satu saluran, tanpa metode tambahan pada objek.

Default topeng 0xffffffff tidak akan memengaruhi kode yang ada.

Apa yang dikatakan @satori99 .

Meskipun, saya pikir mask seharusnya menjadi properti Light dan Mesh*Material , sebagai gantinya. (Hanya material yang terkena cahaya.)

Selain itu, properti juga dapat diberi nama lightMask , lightChannel , atau channel .

Masalah dari pendekatan saluran/masker adalah bahwa pengguna perlu memahami operasi bitwise. Agak terlalu intens jika Anda membandingkannya dengan API lainnya.

Apa yang dapat Anda lakukan dengan topeng yang tidak dapat Anda lakukan dengan pendekatan array?

Saya bisa memberikan contoh dari tugas dengan dua kamar di atas.

Poin utama menggunakan pendekatan saluran daripada pendekatan larik adalah bahwa operasi sederhana seperti 'memindahkan cahaya1 dari ruang 1 ke ruang 2' menjadi lebih rumit jika Anda menggunakan larik.

Alih-alih hanya mengatur

light1.channel = 2

(sebelumnya disetel ke 1)

Anda harus menemukan semua objek di ruang 1 yang memiliki light1 di larik lightInfluences sebelumnya, lalu menghapus cahaya dari lariknya, lalu menambahkannya ke semua benda di ruang 2.

Cerita yang sama dengan operasi sederhana seperti 'memindahkan objek 1 dari kamar 1 ke kamar 2'. Alih-alih mengatur saluran pengaruhnya dari 1 ke 2, Anda perlu menemukan semua lampu di ruangan itu, lalu menghapusnya dari larik pengaruhnya, lalu menemukan semua lampu di kamar dua dan menambahkannya.

Bukannya itu tidak bisa dilakukan, itu sebabnya saya mengatakan bahwa pendekatan lightInfluences baik-baik saja bagi saya. Tetapi hal-hal saluran akan menjadi hal pertama yang akan saya terapkan di atasnya untuk diri saya sendiri hanya untuk membuat operasi umum sesederhana 1 tugas.

Saya pikir itu harus diterapkan sebagai topeng. (Apakah itu diimplementasikan pada CPU atau GPU adalah masalah untuk diskusi nanti.)

Kami dapat menunjukkan melalui contoh cara mengaturnya, dan pengguna dapat mengikuti polanya.

Jika menurut Anda masih terlalu rumit, maka kita bisa membuat THREE.Channels API untuk itu.

light.channels = new THREE.Channels();
...
light.channels.clear();
light.channels.add( channel );
light.channels.remove( channel );
light.channels.all();

Metode yang sama untuk Mesh*Material .

Saya suka API itu :)
Saya dapat melihat ini bekerja untuk objek dan lampu, tetapi bagaimana Anda melihatnya bekerja untuk bahan?

Hanya bahan yang merespons lampu. Ini harus menjadi properti materi, saya akan berpikir.

Saya setuju dengan ini dengan @westlangley. Lampu tergantung pada bahan.

Cerita yang sama dengan operasi sederhana seperti 'memindahkan objek 1 dari kamar 1 ke kamar 2'.

Nah, itu masalah. Channels tidak akan berbasis objek.

Nah, itu masalah. Saluran tidak akan berbasis objek.

Tapi kenapa? Apakah itu batasan teknis?

Karena itu semacam membatalkan seluruh gagasan tentang semua itu. Karena mungkin ada objek yang berbeda, yang menggunakan kembali bahan yang sama, tetapi salah satunya harus menyala dan yang lainnya -- tidak.

Tapi kenapa? Apakah itu batasan teknis?

Tidak. Itu karena benda tidak merespon cahaya. Hanya bahan yang bisa.

Karena mungkin ada objek yang berbeda, yang menggunakan kembali bahan yang sama, tetapi salah satunya harus menyala dan yang lainnya -- tidak.

Anda dapat menggunakan materi yang sama untuk semua objek dalam adegan -- cukup clone materi untuk objek yang materinya memerlukan nilai seragam yang berbeda. Seharusnya masih ada hanya satu program shader yang dibagikan oleh semua.

Saya pikir itu harus diterapkan sebagai topeng. (Apakah itu diimplementasikan pada CPU atau GPU adalah masalah untuk diskusi nanti.)

Bisakah ini ditangani dengan mudah di GPU secara langsung?

Bisakah ini ditangani dengan mudah di GPU secara langsung?

Ya, Anda harus memasukkan seragam channels untuk lampu dan bahan.

Bagaimana dengan sistem manajemen lapisan? Saya akan mengelompokkan jerat menjadi beberapa lapisan dan menerapkan topeng dari sana (dapat memengaruhi cahaya, bayangan, visibilitas, dll), kesatuan akan menjadi contoh yang baik?

Bayangan juga merupakan topik terkait. Saya pikir juga harus ada sesuatu seperti casting bayangan selektif. Seperti 'receiveShadowFrom = ...' (dan daftar sumber) alih-alih hanya 'receiveShadow = true'.

Karena ketika Anda mengatur lampu yang hanya mempengaruhi ruangan tertentu (dalam contoh saya), Anda juga akan segera menginginkan lampu tersebut untuk memberikan bayangan hanya pada objek ruangan ini.

Atribut bayangan harus benar-benar ada pada materi dan bukan objek untuk alasan yang sama seperti di atas di utas ini.

Atribut bayangan harus benar-benar ada pada materi dan bukan objek untuk alasan yang sama seperti di atas di utas ini.

Ya, itu masuk akal!

Apakah ada rencana untuk menyertakan fitur ini (seperti rilis target yang direncanakan untuk draf pertama)?

Sebagai solusi, dapatkah Anda mencapai sebagian besar kebutuhan Anda dengan memiliki pemandangan terpisah untuk setiap ruangan (dan lampunya)?

renderer.autoClear = false;
...
renderer.render( scene1, camera );
renderer.render( scene2, camera );

Hmm, saya akan mencoba pendekatan ini!

Pencahayaan / bayangan selektif adalah suatu keharusan untuk versi IMO mendatang.

BIG +9999 untuk yang satu ini, saya ingin sekali dapat memilih apakah suatu material menghasilkan bayangan dari sumber cahaya A atau dari sumber cahaya B. Adakah yang punya solusi saat ini selain dari dua adegan? Itu akan membuat segalanya sangat menyakitkan bagiku...

omong kosong bagaimana ini masih belum diterapkan? setelah +9999 dari rohan )

Haha tebakan saya agak sulit untuk mengimplementasikan @tsone, bisakah Anda memberikan beberapa info tentang komit itu? Browsing di klien telepon sekarang

betapa sulitnya menerapkan jika ini hanya seragam yang mereka berikan ke materi. yang harus mereka lakukan adalah mengganti daftar lampu global dengan yang ditentukan dalam materi, jika ada, di suatu tempat jauh di dalam penyaji webgl.

Berikut adalah JSFiddle sederhana yang menguji implementasi Layers cabang Dev:
https://jsfiddle.net/Angrypickle/t8f7q3vo/4/
Sayangnya, pada saat ini, sepertinya tidak berfungsi dengan baik. Atau apakah saya melakukan sesuatu yang salah?

Ya. Lapisan belum berfungsi dengan lampu. Mereka memang bekerja dengan kamera/objek! 😊

Pahami itu Pak! Berikut adalah JSFiddle yang diperbarui yang menggunakan kamera yang tumpang tindih untuk mencapai pencahayaan selektif dengan lapisan:
https://jsfiddle.net/Angrypickle/t4a1eusL/
Tampaknya berfungsi dengan baik di desktop dan seluler. Adakah yang melihat sesuatu yang sangat buruk dengan pendekatan ini? Setidaknya sampai lampu diikat ke dalam fungsionalitas lapisan?

Adakah yang melihat sesuatu yang sangat buruk dengan pendekatan ini?

tentu saja itu buruk. daripada memiliki satu kamera menavigasi adegan, orang sekarang harus melakukan hal-hal camera1.add( camera2 ); Maksud saya ini adalah WTF ketika saya melihatnya. Seperti apa? kamera di kamera saya? bagaimana jika saya memiliki lusinan ruangan yang perlu dinyalakan satu per satu? berapa banyak kamera yang saya butuhkan? dan lapisan ... tidak ada lapisan kemarin, benar, dan sekarang saya harus l̲e̲a̲r̲n̲ tentang mereka.

kata-kata kasar, bukan untuk mengatakan saya memiliki solusi sempurna untuk ini. misalnya orang alternativa3d biasa menyalakan lampu pada barang-barang yang ada di kotak pembatas cahaya. ini memiliki keuntungan dari penyiapan next-to-0 untuk pengguna akhir, tetapi itu berantakan ketika batas antara lampu harus berada di sudut. tapi tetap saja, jika saya harus menyelesaikan masalah ini dalam proyek aktual sekarang, saya kemungkinan besar akan memutuskan untuk menggores bahan standar bekas ke dalam ShaderMaterial-s dan meneruskan lampu yang saya inginkan dengan tangan di sana.

Lapisan @makc sebenarnya sangat sederhana (dan kuat)!
Pendekatan @Zob1 jelas bukan pendekatan yang tepat. Mudah-mudahan tidak butuh waktu lama sampai lapisan juga bekerja dengan lampu.

Teman-teman hanya untuk memastikan saya mengikuti dengan benar; katakanlah saya memiliki satu adegan dan sumber cahaya "utama". Mungkinkah dengan teknik ini material tertentu mengabaikan sumber cahaya utama ini, sementara juga mengeluarkan bayangan dari sumber cahaya yang berbeda?

Nah, untuk itu kita juga harus menambahkan lapisan pendukung ke material.

Yang bisa kita lakukan saat ini adalah menampilkan/menyembunyikan objek dari kamera:

Katakanlah Anda sedang melakukan permainan dan, di editor, Anda menggunakan bola untuk menampilkan Collider. Bola tersebut dapat disetel ke lapisan 1, editor kamera dapat mengaktifkan lapisan 0 dan 1, tetapi kamera game dapat disetel ke lapisan 0. Dengan begitu, di editor Anda, Anda melihat semua boneka, tetapi di dalam game mereka ' kembali pergi.

Saya pikir ini akan lebih masuk akal setiap kali saya menambahkan fungsionalitas ke editor itu sendiri. Kita mungkin harus melakukan beberapa contoh juga.

Benar! Jadi pada dasarnya yang ingin saya lakukan adalah, saya memiliki karakter 2D di dunia Tiga JS saya. Karakter-karakter ini membutuhkan bayangan "spot" untuk membuatnya terlihat seperti bagian dari lingkungan. Saat ini saya mencapai ini menggunakan geometri lingkaran hitam transparan yang ditempatkan di kaki mereka dan beberapa hal yang cukup rumit untuk membuatnya bekerja pada sudut. Bahkan kemudian itu tidak bekerja dengan baik sama sekali pada permukaan yang kompleks.

Ide awal saya adalah menempatkan geometri lingkaran tak terlihat sebagai "lingkaran cahaya" di atas setiap karakter dan menciptakan cahaya yang mengarah langsung ke bawah, menutupi seluruh pemandangan. Lingkaran cahaya ini hanya akan memberikan bayangan dari sumber cahaya ini sementara segala sesuatu yang lain dalam pemandangan akan memberikan bayangan dari sumber cahaya "utama".

Saya kira agar ide ini berhasil, kita perlu lapisan bukan?

Lingkaran cahaya ini hanya akan memberikan bayangan dari sumber cahaya ini sementara segala sesuatu yang lain dalam pemandangan akan memberikan bayangan dari sumber cahaya "utama".

Kami dulu memiliki opsi shadowOnly , tetapi opsi itu telah dihapus.

FWIW, ada pendekatan untuk membuat bayangan ini...

Ah tapi shadowOnly tidak akan benar-benar berfungsi karena lingkaran cahaya itu akan mengeluarkan bayangan dari kedua sumber cahaya, saya hanya ingin mereka mengeluarkan bayangan dari satu sumber.

Saya akan memeriksa contoh itu, di telepon sekarang tetapi terlihat menjanjikan.

Sunting Hmm, tetapi jika bola itu mengubah posisinya di pemandangan dan jala tanah memiliki ketinggian yang bervariasi, apakah bayangannya akan cocok dengan normal permukaan tanah dengan benar?

Tidak...

Ya pikir begitu. Butuh lapisan! Hehe

Hai @rohan-deshpande ,

Ya untuk kasus penggunaan Anda, Anda akan membutuhkan semacam lapisan. Saya adalah orang yang mengimplementasikan fitur shadowmesh beberapa waktu lalu. Mereka dimaksudkan untuk digunakan untuk pemandangan yang berisi lantai atau tanah datar, karena mereka adalah bayangan satu bidang. Namun, jika Anda membutuhkan bayangan bidang tunggal yang cepat, murah (tapi benar), ini sulit dikalahkan dari segi kinerja. Alasan saya menambahkan ini adalah karena bahkan untuk adegan demo sederhana, shadowmaps sangat menurunkan framerate saya. Shadowmeshes di sisi lain berjalan cepat bahkan di ponsel saya.

Anda dapat melihat game saya yang menggunakannya di sini:
https://github.com/erichlof/3dLightCycles

Saya merender adegan dua kali melalui 2 viewport yang berbeda dan semua objek game (siklus dan dinding jejak) memiliki bayangan yang benar. Ini berjalan mulus seperti sutra di ponsel cerdas saya, yang tidak mungkin dilakukan dengan peta bayangan untuk 2 rendering adegan setiap bingkai.

+1 di sini untuk lapisan di masa mendatang :)

Game @erichlof terlihat dan berjalan dengan baik di iPhone6 ​​man.

Oke saya kira saya akan menunggu lapisan. Sampai saat itu solusi hacky saya harus cukup.

Tidak, itu belum diterapkan. Anda harus menunggu lapisan atau mencoba salah satu solusi yang tercantum di ITT (misalnya adegan terpisah).

+99999 lagi

Ini pasti akan sangat membantu. Dan kami sekarang memiliki lapisan yang berfungsi, yang sepertinya menahan ini. Jadi, inilah benjolan ramah. ;-)

@manthrax periksa ini!

+99999 lagi

Saya akan senang untuk ini. Saya memiliki situasi di mana setiap avatar hanya diterangi oleh cahaya terdekat, dan saya dapat memiliki ribuan lampu ke dalam pemandangan, akan lebih baik untuk menentukan satu cahaya untuk setiap avatar.

Hai!
Saya akan membutuhkan fitur ini, dan saya berpikir untuk mengimplementasikannya, karena saya pikir saya telah menemukan di mana ini dapat dilakukan ( initMaterial in WebGLRenderer ) dan seharusnya cukup mudah digunakan lapisan yang ada.

Saya sedang berpikir untuk membuat topeng bit khusus cahaya (sebagai objek Layers ) untuk memilih lapisan mana yang dipengaruhi oleh objek cahaya tertentu (tidak tergantung pada lapisan objek cahaya itu sendiri), kemudian memfilter lampu/peta bayangan yang ditetapkan sebagai seragam untuk setiap objek dalam fungsi yang disebutkan di atas.

Apakah itu relevan?

Saya akan mencoba ini dan mengirimkan permintaan tarik segera setelah saya mencapai ini kecuali Anda mengarahkan saya ke beberapa metode lain sebelum itu.

MEMPERBARUI:

https://github.com/tiesselune/three.js/tree/selective-lighting

Aku pergi ke suatu tempat. Tidak yakin bagaimana ini dapat memengaruhi kinerja atau cara mengoptimalkan kode saya untuk kinerja, tetapi ini berhasil pada beberapa tes yang saya buat. Pencahayaan per lapis! Ya!

Saya masih harus menguji lagi, dan membuat contoh yang relevan sebelum mengirimkan permintaan tarik.

MEMPERBARUI:

Saya telah melakukan beberapa tes lagi, dan memiliki materi yang sama pada dua objek yang berada pada lapisan yang berbeda (dan memiliki pengaturan pencahayaan yang berbeda) menyebabkan penyaji memperbarui materi secara konstan (melalui needsUpdate ) sejak pengaturan pencahayaan pada perubahan materi antara dua objek, yang sebelumnya tidak mungkin. Ini berarti penurunan kinerja yang besar dan keanehan visual (karena unggahan materi terakhir menang pada waktu render)

Tentu saja, ini dapat dihindari dengan membuat instance material baru daripada menggunakan yang sama persis untuk dua objek dengan pengaturan pencahayaan yang berbeda. Tapi saya ragu mengkloningnya untuk pengguna adalah ide yang bagus, karena itu berarti menonton materi asli untuk perubahan untuk mencerminkannya ke klon.

Berikut adalah dua solusi yang bisa saya gunakan:

  1. Saya hanya bisa menampilkan peringatan ketika dua objek pada lapisan yang berbeda dengan pengaturan pencahayaan yang berbeda berbagi materi yang sama, sehingga pengguna dapat membuat dan mengelola materi klon baru sendiri.

  2. Saya bisa menambahkan lapisan pada tingkat material alih-alih tingkat objek (dan membuat sistem lapisan paralel untuk lampu) sehingga wajib menggunakan bahan yang berbeda untuk mencapai pengaturan pencahayaan yang berbeda. Itu berarti akan ada sistem lapisan saat ini untuk visibilitas (pada objek dan kamera) dan yang berbeda untuk pencahayaan (pada bahan dan lampu).

apa yang kalian pikirkan?

Saya baru saja memikirkan hal ini ketika saya melihat komentar Anda masuk. Saya pikir menampilkan peringatan tidak membantu, karena banyak orang mungkin tidak akan melihatnya. Dari keduanya, saya pasti lebih suka mengatur lapisan cahaya pada materi daripada pada objek. Ini sedikit kontra-intuitif, tapi masih masuk akal.

Hanya untuk memperjelas, ketika needsUpdate disetel, dalam hal ini, itu hanya menghitung ulang nilai seragam, bukan? Seharusnya tidak perlu mengkompilasi ulang shader karena shader yang berbeda semuanya harus di-cache. Apa jenis hit kinerja yang Anda lihat? Apakah Anda menggunakan profiler untuk melihat dengan tepat di mana perhitungan ekstra terjadi?

Omong-omong, filterAmbiantLights seharusnya filterAmbientLights .

Anda benar tentang kesalahan ejaan. Saya sebenarnya telah menulis semuanya dengan "ambiant" sebelum menyadari itu salah dan saya lupa sebuah kejadian. 😇

Saya pikir saya akan memindahkan info lapisan pada materi itu. Tampaknya lebih relevan dan konsisten dengan cara kerjanya.

Penurunan kinerja datang (dan masih datang) dari initMaterial (dan kemudian acquireProgram dan getShaderParameter yang sangat lambat untuk beberapa alasan) dipanggil setiap frame beberapa kali karena lightHash akan berbeda setiap saat, menyetel material.needsUpdate ke true .

BTW Saya menggunakan alat profil Chrome. (Garis waktu dan profiler).

Tidak apa-apa bagi saya, tetapi saya tidak jelas mengapa acquireProgram harus berjalan sepanjang waktu. Jika jumlah setiap jenis cahaya ditambahkan ke parameter program, bukankah mengkompilasi ulang shader setiap kali tidak diperlukan?

Saya juga tidak mengerti;

Inilah tumpukan panggilan (di setiap bingkai) dan kebocoran memori mengerikan yang mengikuti, jika Anda terbiasa dengan ini, itu dapat membantu saya memahami apa yang salah. Sepertinya itu membuat WebGLProgram s baru setiap frame...

threejscalltree

Mungkin replaceLightNums yang memperbarui kode shader simpul/fragmen selama pembuatan Program WebGL, menyebabkannya dikompilasi ulang, atau menganggapnya sebagai shader yang berbeda... ?

EDIT: Bagaimanapun, menggunakan lapisan pada tingkat material memecahkan masalah seperti yang diharapkan. Saya hanya memiliki kebocoran memori di suatu tempat yang harus saya selidiki tetapi selain itu terlihat cukup bagus.

Mungkin ide yang baik untuk memahami mengapa ini terjadi hanya untuk memastikan Anda sepenuhnya memahami kode dan tidak memperkenalkan beberapa bug baru. Bisakah Anda menelusurinya untuk melihat mengapa kode shader mengubah setiap bingkai?

Saya tidak tahu WebGLPrograms cukup baik untuk mengatakan apa yang terjadi, tetapi sepertinya itu harus menyimpan shader itu untuk Anda.

Ini cukup sederhana, sebenarnya:

  • untuk mengetahui apakah akan menelepon atau tidak acquireProgram , initMaterial mendapatkan "kode" shader dari cache (sebenarnya ini lebih merupakan hash, dibangun di getProgramCode ) dan membandingkan ke "kode" program materi saat ini.
  • Karena fungsi ini menciptakan "kode" dari parameter termasuk jumlah setiap jenis cahaya, yang disaring dan meskipun berbeda antar objek, kode dapat berbeda untuk bahan yang sama ( bisa dikatakan, program yang sama) dari objek ke objek lainnya.
  • Karena proses ini diulang untuk setiap objek, "kode" berubah beberapa kali per frame, menyebabkannya mengkompilasi ulang sebanyak mungkin dalam satu frame: yang menyebabkan penurunan perf.
  • Yang mengatakan, karena beberapa objek memiliki bahan yang sama, dan dengan demikian, program yang sama, objek terakhir yang diulang melalui memaksakan parameternya ke program, yang menyebabkan kedua objek dinyalakan dengan pengaturan cahaya yang sama tetapi tidak harus dengan shadowMaps yang sama (yang dapat dihitung untuk objek dalam urutan yang berbeda, tetapi mengalami masalah "objek terakhir menang" yang sama), menyebabkan keanehan visual saya.

Sekarang semuanya bekerja seperti yang diharapkan (karena setiap objek dengan pengaturan cahaya yang berbeda memiliki materi yang berbeda dan program yang berbeda), kecuali untuk pengoptimalan memori yang dapat saya lakukan dengan hash cahaya saya sendiri, yang akan segera saya tangani.

Mungkin ada beberapa peningkatan jika angka-angka ringan bervariasi, sehingga setiap materi hanyalah contoh dari program yang sama, tetapi karena angka-angka itu dimasukkan ke dalam kode shader (dalam replaceLightNums ) tampaknya tidak sesuai dengan keadaan saat ini adalah (dan pengoptimalannya).

Semoga penjelasannya cukup dimengerti

Saya ingin tahu apakah kita bisa meneruskan layer mask ke shader (satu seragam per objek dan satu seragam lagi per cahaya). Kemudian kita bisa menambahkan sesuatu seperti ini di sini .

Sesuatu seperti...

for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {

    pointLight = pointLights[ i ];
    pointLight.distance *= float( object.mask & pointlight.mask > 0.0 );

    ...

}

Meh, saya tidak berpikir kita bisa melakukan operasi bitwise di glsl...

Ya, sepertinya operasi bitwise dimulai di GLSL 1.30 dan WebGL standar itu menggunakan 1.00. 😕

Hai @mrdoob dan @tiesselune ,

Chrome 56 dan Firefox 51 baru saja mendarat, yang berarti WebGL 2.0 diaktifkan secara default (WebGL2 mengikuti spesifikasi OpenGL ES 3.0). Itu berarti bahwa operasi Bit (dan hal-hal keren lainnya seperti tekstur 3d) sekarang tersedia. Saya tidak tahu apakah Three perlahan-lahan mempersiapkan peralihan ke WebGL 2.0, tetapi saya membuat beberapa perubahan wajib pada salinan three84.js saya dan mengaktifkan WebGL 2.0, dan melakukan sedikit operasi di shader hanya untuk memastikannya berhasil, dan berhasil!
https://developers.google.com/web/updates/2017/01/nic56
https://developer.mozilla.org/en-US/Firefox/Releases/51

Hanya ingin kamu tahu. +1 untuk ide penyamaran :-)

Hai @erichlof ! Itu berita bagus untuk WebGL2; itu berarti perender WebGL2 mungkin akan dapat mendekati masalah penyamaran dengan cara yang lebih efisien.

Bagaimanapun, mengingat penggunaan browser yang mendukung WebGL2 sangat terbatas sejauh ini, saya tidak berpikir kita dapat membuang upaya untuk membuatnya bekerja di WebGL 1 : butuh waktu lama sampai hampir semua browser dapat menjalankan aplikasi WebGL, jadi mungkin akan sedikit lebih lama sampai WebGL 2 benar-benar dapat digunakan dalam skala besar... Tapi terima kasih atas petunjuknya!

Halo lagi!

Pembaruan baru: Saya telah melakukan apa yang saya pikir perlu untuk manajemen memori, tetapi pengumpulan sampah tumpukan JS tampaknya banyak berkaitan dengan konfigurasi perangkat lunak saya (menjalankan program, membuka tab, ekstensi) pada saat saya menjalankan profil. Dapatkah seseorang dengan sedikit lebih banyak pengalaman mengonfirmasi bahwa kode saya tidak terlalu haus memori dibandingkan dengan versi threejs saat ini?

Bagaimanapun, saya sudah membuat contoh di example /webgl_lights_selective_lighting.html . Masalahnya, saya mendapatkan artefak visual terkait shadowmap saat menggunakan dua lampu sorot (pada lapisan yang sama) secara bersamaan pada objek adegan yang dikuliti. Objek statis berperilaku seperti yang diharapkan. Saya telah menjalankan tes dan itu terjadi di cabang dev juga, tanpa mempertimbangkan lapisan cahaya selektif sama sekali (sebenarnya, saya baru saja menambahkan sorotan dalam contoh shadowmap, di cabang dev). Apakah ada yang tahu dari mana itu berasal?

Berikut screenshotnya:
shadowmap

Seharusnya dimungkinkan untuk melihat contoh langsung di sini:

https://rawgit.com/tiesselune/three.js/selective-lighting/examples/webgl_lights_selective_lights.html

Saya mendapatkan kesalahan:

Uncaught TypeError: Cannot read property 'set' of undefined
    at init (webgl_lights_selective_lights.html:117)
    at webgl_lights_selective_lights.html:67

@looeee : Anda harus menjalankan npm run build-uglify pada host lokal. Saya secara sukarela tidak menyertakan build dalam commit saya untuk tujuan penggabungan...

Atau haruskah saya?

EDIT: inilah tautan yang berfungsi di cabang yang berbeda untuk tujuan pengujian: https://rawgit.com/tiesselune/three.js/selective-lights-test/examples/webgl_lights_selective_lights.html

Hai, +999999 dari saya. Ini harus diterapkan (setidaknya dengan THREE.Layers )

$$('.comment-body').reduce((acc, el) => {
  let mat = el.textContent.match(/\+(\d+)/)
  let num = +(mat && mat[1] || 0)
  return acc + num
}, 0)
>> 1219997

🤔

@mrdoob dia menghitung +N di utas ini

btw, +14570 untuk lampu selektif

Ini akan sangat bagus untuk menyempurnakan cara kerja pencahayaan dalam abstraksi yang lebih tinggi.

Misalnya dalam pena berikut, saya ingin pencahayaan bekerja satu arah untuk elemen DOM vs cara lain untuk Sphere agar pencahayaan menjadi lebih realistis:

https://codepen.io/trusktr/pen/RjzKJx

Efek tertentu yang terlihat seperti satu titik-cahaya dapat dicapai dengan menggabungkan dua atau lebih lampu yang secara selektif hanya mempengaruhi elemen tertentu.

Misalnya, dalam contoh saya sebelumnya, saya dapat meningkatkan intensitas cahaya untuk mendapatkan bayangan yang bagus pada "elemen DOM", tetapi kemudian Sphere akan terlihat sedikit terlalu berkilau dan cerah. Jika saya dapat memiliki cahaya yang lebih redup untuk Sphere, dan cahaya yang lebih terang untuk "elemen DOM", maka saya dapat mencapai sesuatu yang lebih realistis dengan cara ini, di mana tampaknya bagi pemirsa bahwa hanya ada satu cahaya. Kemudian hal semacam ini dapat diabstraksikan dalam API tingkat yang lebih tinggi yang membuatnya tampak seperti hanya ada satu cahaya yang dimanipulasi ketika di belakang layar dua lampu Three.js benar-benar sedang dimainkan.

@WestLangley

Sebagai solusi, dapatkah Anda mencapai sebagian besar kebutuhan Anda dengan memiliki pemandangan terpisah untuk setiap ruangan (dan lampunya)?

Apakah Anda memiliki tautan ke contoh sesuatu seperti ini? Bisakah itu memiliki efek rendering tak terduga lainnya pada hasilnya?

efek rendering tak terduga lainnya pada hasil?

urutan rendering objek transparan, misalnya - objek transparan di adegan 1 akan dirender sebelum objek buram di adegan 2.

Apakah Anda memiliki tautan ke contoh sesuatu seperti ini?

di sini, saya membuat satu hanya untuk Anda: https://jsfiddle.net/f2Lommf5/524/

urutan rendering objek transparan, misalnya - objek transparan di adegan 1 akan dirender sebelum objek buram di adegan 2.

Itulah yang saya pikirkan; itu membuat solusi hanya solusi untuk kasus yang sangat terbatas. Menantikan solusi nyata!

Nah, Anda dapat berargumen bahwa masalah hanya akan terjadi jika Anda dapat melihat objek buram dari scene2 dari scene1 melalui objek transparan tersebut. tetapi jika itu masalahnya, lampu juga harus melewatinya, dan tidak akan ada alasan untuk memisahkan adegan sejak awal. tapi saya setuju argumen semacam ini tidak terlalu meyakinkan.

@makc Berikut ini contoh masalah yang saya coba selesaikan:

https://discourse.threejs.org/t/how-to-make-shadows-darker-on-transparent-objects/1389

Saya pikir pencahayaan selektif akan sangat membantu dalam hal ini.

@trusktr Saya pikir Anda dapat menyelesaikannya dengan mengubah materi bayangan mrdoob. itu hanya menunjukkan tekstur bayangan hitam-putih, dan Anda dapat memodifikasinya menjadi transparan seperlunya

Masker di PlayCanvas tampaknya sangat mudah digunakan untuk pencahayaan selektif: https://forum.playcanvas.com/t/set-certain-object-to-not-receive-light/785.

bisakah kita menggabungkan ini? Saya pikir masalah bayangan itu karena shader Lambert tidak ada hubungannya dengan perubahan kode. @tiesselune

@ErikBehar Saya sebenarnya mencari sesuatu untuk dilakukan sore ini, saya akan mencoba memperbarui kode ke threejs terbaru dan mengirimkan permintaan tarik mungkin? Saya benar-benar senang mengetahui bahwa saya memberikan kontribusi nyata untuk proyek sebesar itu. (Dan bagus untuk mendapatkan konfirmasi bahwa bug ini tidak ada hubungannya dengan perubahan saya)

EDIT: baru saja menemukan bahwa bagian kode ini banyak berubah. Saya kira akan membutuhkan sedikit waktu karena status yang saya gunakan sebelumnya dipindahkan dari WebGLRenderer ke WebGLLights.

@tiesselune Saya agak perlu memasukkan ini ke dalam proyek jadi saya melanjutkan dan mem-porting kode Anda ke v93, lihat: https://github.com/ErikBehar/three.js/tree/selectiveLights

Saya bisa mengerjakan PR jika kalian mau? @mrdoob

@ErikBehar Yah itu memang terlihat seperti apa yang saya tuju tetapi saya tidak punya waktu untuk melakukannya sepenuhnya. Saya pikir saya akan memindahkan fungsi pemfilteran/hash dari WebGLRenderer dan menambahkannya ke objek status WebGLLights. Saya merasa mereka berada di sana sekarang, sistem lapisan menjadi bagian dari negara bagian dan bukan bagian dari penyaji.

@ErikBehar seorang PR akan sangat bagus!

@tiesselune Saya akan mempertimbangkan untuk memindahkannya seperti yang Anda sarankan, atau jangan ragu untuk mendorong PR di garpu saya lol = ] dan saya akan segera memposting PR @mrdoob

Ini statusnya apa? Saya telah menggabungkan kode r94dev dari @ErikBehar ke r94, lalu menggabungkan r97 ke dalamnya, hanya beberapa konflik yang sangat mudah (perubahan versi, beberapa variabel untuk pencahayaan selektif, dan pembuatan hash di renderers/WebGLRenderer.js; saya akan dengan senang hati memasukkan PR. @tiesselune jika Anda dapat memberi saya beberapa ide ke mana Anda ingin pergi ke keadaan pencahayaan selektif, saya akan dengan senang hati memindahkannya, mengujinya, dan memasukkannya ke dalam PR.

EDIT:
Beberapa saat kemudian: Saya melihat bahwa ini membutuhkan beberapa pekerjaan untuk berfungsi, sekarang, dengan lighthash baru.

@VaelynPhi Saya akan berpikir bahwa, terlepas dari apakah mereka bersedia menerima kode @ErikBehar atau tidak, adalah ide yang baik untuk mengirimkan PR, hanya untuk mengganti yang usang jika orang lain menginginkannya, seperti Anda sendiri telah melakukan

Maaf menjatuhkan bola pada ini guys = / ... @VaelynPhi dapatkah Anda memposting garpu / cabang Anda?

Jangan khawatir; Saya mengerti menjadi sibuk. Sayangnya, saya tidak bisa mendapatkan bahkan cabang tempat Anda bekerja, @ErikBehar; Saya memutuskan untuk membaca kode untuk mencoba dan memecahnya sehingga saya dapat memindahkan status ke lokasi yang sesuai dan mudah-mudahan memperbaiki bug apa pun. Saya belum mencapai status port yang berfungsi bahkan pada v94. Mungkin saya bisa membersihkannya dan memasukkan PR hanya untuk memperbaruinya seperti yang disarankan @makc . Beri aku sedikit; Saya sangat sibuk. :) Setidaknya mungkin itu akan membantu menyoroti perubahan yang perlu dilakukan untuk menarik pencahayaan selektif ke versi terbaru.

menambahkan PR berdasarkan:
https://github.com/ErikBehar/three.js/commit/ac0499b70b82bc7bb780100a8372fcdf318d1424#diff -5e43a0b5002eb2c419def3baf67d4e67
oleh @ErikBehar
adakah yang bisa membantu dengan beberapa ulasan dan contohnya?

https://github.com/mrdoob/three.js/pull/15223

Gan, ini statusnya apa ya? @tiesselune @ErikBehar Bolehkah saya membantu Anda dengan sesuatu? Akan menyenangkan untuk menerapkannya akhirnya setelah 4 tahun

@flyrell Saya pikir kita mungkin bisa menutup masalah ini karena tampaknya hampir selesai di #15223 mungkin?

Apakah halaman ini membantu?
0 / 5 - 0 peringkat