Rumah  >  Artikel  >  hujung hadapan web  >  Perbincangan ringkas tentang aplikasi needsUpdate dalam kemahiran tutorial three.js_html5

Perbincangan ringkas tentang aplikasi needsUpdate dalam kemahiran tutorial three.js_html5

WBOY
WBOYasal
2016-05-16 15:50:572638semak imbas

Banyak objek dalam three.js mempunyai atribut needsUpdate, yang jarang disebut dalam dokumentasi (tetapi tidak terdapat banyak dokumen untuk three.js, dan banyak masalah perlu diselesaikan oleh isu pada github dalam pelbagai tutorial di Internet I). Saya tidak begitu mahir menulis ini, kerana untuk program peringkat kemasukan yang mudah, atribut ini tidak digunakan.
Jadi untuk apa atribut ini digunakan? Secara ringkasnya, ia memberitahu pemapar bahawa saya harus mengemas kini cache untuk bingkai ini Walaupun ia sangat mudah digunakan sebagai bendera, kerana anda ingin tahu mengapa cache perlu dikemas kini, anda perlu Cache mana yang dikemas kini, jadi perlu memahaminya dengan teliti.
Mengapa needsUpdate diperlukan
Pertama sekali, mari kita lihat sebab cache diperlukan secara amnya untuk mengurangkan bilangan penghantaran data, dengan itu mengurangkan masa yang dibelanjakan oleh program penghantaran data. Di sini adalah sama Secara amnya, tidak mudah untuk objek (Mesh) berjaya dipaparkan pada skrin Ia perlu dipindahkan ke medan perang sebanyak tiga kali
Pertama, semua data puncak dan data tekstur. baca dari cakera tempatan ke dalam memori melalui program.
Kemudian selepas program telah melakukan pemprosesan yang sesuai dalam ingatan, ia akan memindahkan data puncak dan data tekstur objek yang perlu dilukis ke skrin ke memori video.
Akhir sekali, apabila memaparkan setiap bingkai, data bucu dan data tekstur dalam memori video dipancarkan kepada GPU untuk pemasangan dan lukisan.
Menurut model penghantaran data piramid, langkah pertama jelas adalah yang paling perlahan Jika ia dihantar melalui rangkaian dalam persekitaran seperti WebGL, ia akan menjadi lebih perlahan ingatan. Ujian data mudah akan dilakukan kemudian.
Kemudian terdapat kekerapan penggunaan ketiga-tiga langkah ini Untuk adegan kecil, langkah pertama adalah operasi sekali, iaitu, semua data adegan akan dimuatkan ke dalam memori setiap kali program dimulakan. . Untuk Untuk senario berskala besar, beberapa pemuatan tak segerak mungkin dilakukan, tetapi ia tidak sedang dipertimbangkan. Kekerapan langkah kedua harus menjadi perkara yang paling penting untuk dibincangkan kali ini Pertama, tulis program mudah untuk menguji penggunaan yang disebabkan oleh langkah penghantaran ini

<.>Salin kodKodnya adalah seperti berikut:
var canvas = document.createElement('canvas'); 'eksperimen -webgl');
var vertices = [];
for(var i = 0; i < 1000*3; i ){
vertices.push(i * Math.random() );
}
var penimbal = _gl.createBuffer(); 🎜> fungsi bindBuffer(){
for(var i = 0; i < 1000; i ){
_gl.bindBuffer(_gl.ARRAY_BUFFER, buffer); Float32Array (bucu), _gl.STATIC_DRAW);
}
}


Izinkan saya menerangkan secara ringkas program ini dahulu ialah tatasusunan yang menyimpan bucu Di sini, 1000 bucu dijana secara rawak Kerana setiap bucu mempunyai tiga koordinat: x, y dan z, tatasusunan 3000 diperlukan Perintah _gl.createBuffer membuka penimbal dalam memori video untuk menyimpan data puncak, dan kemudian menggunakan _gl.bufferData untuk memindahkan salinan data puncak yang dijana daripada memori ke memori video. Diandaikan di sini bahawa terdapat 1000 objek dengan 1000 bucu setiap puncak adalah 3 data apungan 32 bit dan 4 bait Selepas pengiraan, ia hampir 1000 x 1000 x 12 = 11M data. Masa 15ms, di sini anda mungkin melihat bahawa 15ms hanyalah jumlah masa yang begitu kecil, tetapi untuk program masa nyata, jika anda ingin memastikan kadar bingkai 30fps, masa yang diperlukan untuk setiap bingkai harus dikawal pada kira-kira 30ms, yang hanya untuk melakukan data sekali. Penghantaran hanya mengambil separuh masa Anda mesti tahu bahawa kepala besar harus menjadi operasi lukisan dalam GPU dan pelbagai pemprosesan dalam CPU.
Jadi bilangan penghantaran dalam langkah ini harus diminimumkan, sebenarnya, semua data puncak dan data tekstur boleh dipindahkan dari memori ke memori video sebaik sahaja ia dimuatkan . Pertama Pada masa ini, data puncak objek (Geometri) yang perlu dilukis dipindahkan ke memori paparan, dan penimbal dicache ke geometri.__webglVertexBuffer Selepas itu, atribut verticesNeedUpdate Geometri akan dinilai setiap kali ia dilukis. Jika tiada kemas kini diperlukan, cache semasa akan digunakan secara langsung , jika anda melihat bahawa vertexNeedUpate adalah benar, data puncak dalam Geometri akan dihantar semula ke geometri.__webglVertexBuffer Secara amnya, kami tidak memerlukan langkah ini untuk objek statik, tetapi jika kita menemui objek yang bucunya kerap berubah, contohnya, gunakan sistem Zarah yang menggunakan bucu sebagai zarah, dan Mesh yang menggunakan animasi rangkanya akan menukar bucunya setiap bingkai, jadi mereka perlu menetapkan sifat verticesNeedUpdate mereka kepada benar setiap bingkai untuk memberitahu pemapar bahawa saya perlu menghantar semula data.
Malah, dalam program WebGL, kedudukan bucu kebanyakannya ditukar dalam pelorek puncak untuk melengkapkan kesan zarah dan animasi rangka Walaupun ia lebih mudah untuk dikembangkan jika dikira pada bahagian CPU, disebabkan oleh had kuasa pengkomputeran JavaScript , Kebanyakan operasi intensif pengiraan ini akan dilakukan pada bahagian GPU. Dalam kes ini, tidak perlu menghantar semula data puncak, jadi kes di atas sebenarnya tidak banyak digunakan dalam program sebenar Lebih kerap, cache tekstur dan bahan akan dikemas kini.
Kes di atas terutamanya menerangkan adegan penghantaran data puncak Selain data puncak, terdapat juga sebahagian besar tekstur format R8G8B8A8 saiz 1024*1024 akan menduduki sehingga 4M memori. contoh berikut

Salin kod
Kodnya adalah seperti berikut:

var canvas = document. createElement('canvas');
var _gl = canvas.getContext('experimental-webgl'); img. onload = function(){
console.profile('texture test');
bindTexture(); src = 'test_tex.jpg';
function bindTexture(){
_gl.bindTexture(_gl.TEXTURE_2D, texture;
_gl.texImage2D(_gl.TEXTURE_2D, 0. , _gl .UNSIGNED_BYTE, img);
}


Tidak perlu mengulanginya 1000 kali di sini. Ia mengambil masa 30ms untuk menghantar tekstur 10241024 sekali, dan hampir 2ms untuk tekstur 256256. Oleh itu, dalam three.js, tekstur hanya dihantar sekali pada permulaan. maka jika sifat texture.needsUpdate tidak ditetapkan secara manual kepada benar, tekstur yang telah dipindahkan ke memori video akan digunakan secara langsung.
Cache yang manakah perlu dikemas kini
Di atas menerangkan melalui dua kes mengapa three.js perlu menambah atribut needsUpdate. Seterusnya, mari kita senaraikan beberapa senario untuk mengetahui dalam keadaan apa yang diperlukan untuk dilakukan secara manual.
Pemuatan tekstur tak segerak
Ini adalah perangkap kecil, kerana imej bahagian hadapan dimuatkan secara tidak segerak Jika anda menulis texture.needsUpdate=true terus selepas mencipta img, three.js The pemapar akan menggunakan _gl.texImage2D untuk memindahkan data tekstur kosong ke memori video dalam bingkai ini, dan kemudian menetapkan bendera ini kepada palsu Selepas itu, data memori video tidak akan dikemas kini sehingga imej dimuatkan untuk keseluruhan imej dimuatkan dalam acara onload sebelum menulis tekstur.needsUpdate = benar
Tekstur Video
Kebanyakan tekstur hanya memuatkan dan memindahkan imej sekali seperti kes di atas , tetapi tidak untuk tekstur video, kerana video adalah aliran gambar, dan gambar yang akan dipaparkan adalah berbeza dalam setiap bingkai, jadi needsUpdate perlu ditetapkan kepada benar dalam setiap bingkai untuk mengemas kini data tekstur dalam kad grafik.
Gunakan penampan render
Penimbal render ialah objek khas Secara amnya, atur cara memancarkan keseluruhan pemandangan terus ke skrin, tetapi jika terdapat lebih banyak pemprosesan pos atau xxx berasaskan skrin ini (seperti. oklusi ambien berasaskan skrin), anda perlu melukis pemandangan ke penampan render terlebih dahulu. Penampan ini sebenarnya adalah tekstur, tetapi ia dijana oleh lukisan sebelumnya dan bukannya memuatkan daripada cakera. Terdapat objek tekstur khas WebGLRenderTarget dalam three.js untuk memulakan dan menyimpan renderbuffer Tekstur ini juga perlu menetapkan needsUpdate kepada benar dalam setiap bingkai
Keperluan Bahan
Bahan adalah dalam tiga. js diterangkan melalui THREE.Material Sebenarnya, bahan tidak mempunyai apa-apa data untuk dihantar, tetapi mengapa kita perlu membuat kemas kini keperluan Di sini kita juga ingin bercakap tentang shader. yang disediakan dalam gpu Kemungkinan pengaturcaraan untuk memproses bucu dan piksel Dalam lukisan, terdapat istilah teduhan untuk melukis teduhan dalam GPU adalah serupa nyatakan bahan objek ok, kerana shader adalah larian Program pada GPU, seperti semua program, perlu disusun dan dipautkan sekali Dalam WebGL, program shader dikompilasi pada masa larian, yang tentunya memerlukan masa. jadi lebih baik untuk menyusun dan menjalankan program sekali. Oleh itu, dalam three.js, program shader disusun dan dipautkan apabila bahan dimulakan dan objek program yang diperoleh selepas penyusunan dan pemautan dicache. Secara amnya, bahan tidak perlu menyusun semula keseluruhan shader Untuk melaraskan bahan, anda hanya perlu mengubah suai parameter seragam shader. Tetapi jika anda menggantikan keseluruhan bahan, seperti menggantikan shader phong asal dengan shader lambert, anda perlu menetapkan material.needsUpdate kepada true dan compile semula. Walau bagaimanapun, keadaan ini jarang berlaku, dan situasi yang lebih biasa adalah yang disebutkan di bawah.
Menambah dan memadamkan lampu
Ini sepatutnya menjadi perkara biasa dalam adegan sehingga lampu, saya dapati bahawa lampu tidak berfungsi Walau bagaimanapun, ini adalah apabila menggunakan shader terbina dalam three.js, seperti phong dan lambert Jika anda melihat kod sumber dalam pemapar, anda akan mendapatinya three.js berada dalam kod shader terbina dalam Gunakan #define untuk menetapkan bilangan lampu dalam pemandangan, dan nilai #define ini diperolehi dengan penyambung rentetan setiap kali bahan dikemas kini

Salin kod
Kod adalah seperti berikut:

"#define MAX_DIR_LIGHTS " parameter .maxDirLights,
"#define MAX_POINT_LIGHTS " parameters.maxPointLights,
"#define MAX_SPOT_LIGHTS " parameters.maxSpotLights,
"#define MAX_HEMI_LIGHTS "parameters.>
maxHemiLights "
Memang cara penulisan ini dapat mengurangkan penggunaan daftar gpu dengan berkesan Jika hanya ada satu lampu, anda hanya boleh mengisytiharkan pembolehubah seragam yang diperlukan untuk satu lampu, tetapi setiap kali bilangan lampu berubah, terutamanya apabila. menambah Anda perlu menjahit semula, menyusun dan memautkan peneduh Pada masa ini, anda juga perlu menetapkan bahan.keperluanKemas kini semua bahan kepada benar; bukan bermaksud mengemas kini data tekstur, tetapi Ini kerana bahan asal menggunakan tekstur dan kemudian berhenti menggunakannya, atau bahan asal tidak menggunakan tekstur dan kemudian menambahkannya kemudian Jika anda tidak mengemas kini bahan secara manual, kesan akhir akan berlaku menjadi berbeza daripada apa yang anda fikirkan. Sebab-sebab masalah ini adalah seperti berikut Menambah lampu di atas adalah hampir sama, kerana makro ditambahkan pada shader untuk menentukan sama ada tekstur digunakan,



Salin kod
Kod Seperti berikut: parameters.map ? "#define USE_ENVMAP" : "",
parameters.lightMap ? "#define USE_LIGHTMAP" : "",
parameters.bumpMap ? define USE_NORMALMAP" : "",
parameters.specularMap ? "#define USE_SPECULARMAP" : "",


Jadi setiap kali peta, atau envMap atau lightMap menukar nilai sebenar, bahan perlu dikemas kini

Perubahan dalam data puncak lain

Sebenarnya Perubahan tekstur di atas juga akan menyebabkan masalah kerana tiada tekstur semasa pengamulaan, tetapi kemudiannya ditambah secara dinamik persekitaran ini, tidak cukup untuk menetapkan material.needsUpdate kepada benar Anda juga perlu menetapkan geometri.uvsNeedsUpdate kepada true , Mengapa masalah ini berlaku? geometri dan bahan dimulakan buat kali pertama dalam pemapar, jika dinilai bahawa tiada tekstur, walaupun data dalam memori mengandungi data UV untuk setiap bucu , tetapi three.js masih tidak akan menyalin data ini ke video memori. Tujuan asalnya adalah untuk menjimatkan ruang memori video yang berharga, tetapi selepas menambah tekstur, geometri tidak akan menghantar semula data UV untuk kegunaan tekstur secara manual Masalah uv ini benar-benar mengganggu saya untuk masa yang lama pada mulanya.
Untuk mendapatkan maklumat tentang atribut needUpdate beberapa data puncak, sila lihat isu ini
https://github.com/mrdoob/three.js/wiki/Updates
Akhirnya
tiga Pengoptimuman .js adalah baik, tetapi pelbagai pengoptimuman membawa pelbagai perangkap Dalam kes ini, cara terbaik ialah melihat kod sumber atau isu fail pada github.
Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn