kod demo
Jika anda berminat untuk terus ke dalam kod dan mencubanya, anda boleh menemuinya di sini di GitHub.
mahu mencubanya dalam tindakan? Saya mempunyai versi berjalan yang dihoskan di sini: Penapis Realiti.
Nota: Perubahan baru -baru ini dalam cara Chrome mengendalikan input kamera memerlukan halaman untuk dijalankan melalui HTTPS untuk ini berfungsi!
Kami akan mengambil persediaan awal yang sama dari artikel Google Cardboard sebelumnya - adegan tiga.js yang kami paparkan melalui kesan stereoskopik. Kesan itu membolehkan kita mempunyai paparan untuk setiap mata, membuat perkara kelihatan hebat 3D dalam VR. Walau bagaimanapun, daripada zarah terapung dan sebagainya dari artikel sebelumnya, kami mengeluarkan kebanyakan elemen dan meletakkan satu three.js mudah di hadapan kamera yang memainkan suapan kamera kami.
Melihat pengisytiharan pembolehubah kami, kebanyakan pembolehubah di sini akan kelihatan biasa kepada mereka yang telah melalui demo sebelumnya. Pembolehubah untuk menyediakan adegan tiga.js kami, kamera, penerima, elemen untuk output kanvas kami, bekas untuk meletakkan elemen itu dan pembolehubah untuk menyimpan kesan stereoskopik kami adalah sama.
<span>var scene, </span> camera<span>, </span> renderer<span>, </span> element<span>, </span> container<span>, </span> effect<span>,</span>
tiga pembolehubah baru kami yang berkaitan dengan suapan kamera kami adalah video, kanvas dan konteks.
video<span>, </span> canvas<span>, </span> context<span>,</span>
kami mempunyai beberapa pembolehubah lain di bawah yang berkaitan dengan fungsi penapis kami.
themes <span>= ['blackandwhite', 'sepia', 'arcade', 'inverse'], </span> currentTheme <span>= 0, </span> lookingAtGround <span>= false;</span>
kita mulakan dengan fungsi init () kami menyediakan adegan, kamera dan sebagainya seperti dahulu:
<span>init(); </span> <span>function init() { </span> scene <span>= new THREE<span>.Scene</span>(); </span> camera <span>= new THREE<span>.PerspectiveCamera</span>(90, window.innerWidth / window.innerHeight, 0.001, 700); </span> camera<span>.position.set(0, 15, 0); </span> scene<span>.add(camera); </span> renderer <span>= new THREE<span>.WebGLRenderer</span>(); </span> element <span>= renderer.domElement; </span> container <span>= document.getElementById('webglviewer'); </span> container<span>.appendChild(element); </span> effect <span>= new THREE<span>.StereoEffect</span>(renderer); </span> element<span>.addEventListener('click', fullscreen, false);</span>
Kami tidak mempunyai fungsi pergerakan kamera melalui acara peranti ini. Berbanding dengan pengalaman VR, kita tidak perlu menukar kedudukan kamera sebenar dalam adegan tiga.js ini. Kami menjaga tempat kejadian di tempat yang sama - suapan kamera adalah apa yang akan bergerak apabila pengguna melihat -lihat.
Satu pendengar yang kami simpan dari contoh sebelumnya adalah pendengar acara untuk pergi ke skrin penuh jika kami mengetuk tempat kejadian. Ini menghilangkan bar alamat Chrome dari pandangan kami.
Terdapat penggunaan baru untuk perantiOrientationEvent dalam demo ini. Kami menetapkannya untuk menonton perubahan dalam orientasi peranti kami dan menggunakannya sebagai pencetus untuk menukar penapis kami. Kami tidak mempunyai sebarang kawalan fizikal untuk mencetuskan peristiwa, jadi kami mengawal perkara -perkara di mana pengguna mencari. Khususnya, kita menukar penapis pada bila -bila masa pengguna melihat tanah.
<span>var scene, </span> camera<span>, </span> renderer<span>, </span> element<span>, </span> container<span>, </span> effect<span>,</span>
Dalam kod ini, kita lihat sama ada EVT.Gamma adalah antara -1 dan 1. Jika ya, mereka melihat tanah. Ini adalah tempat yang tepat di atas tanah, jika anda merasa terlalu kecil dan sukar untuk dicetuskan, anda boleh meningkatkan julat ke antara -1.5 dan 1.5 ... dan lain -lain
Apabila mereka melihat dalam julat ini dan ketika Lookatground adalah palsu, kami menjalankan Kod Switcher Tema kami. Ini menyesuaikan semasa semasa ke nombor indeks seterusnya dari pelbagai tema kami. Kami menetapkan Lookatground untuk benar dan menetapkannya kembali selepas 4 saat. Ini memastikan kami hanya menukar penapis sekali setiap empat saat.
Untuk menapis dunia di sekeliling kita, kita memerlukan akses kepada kamera "persekitaran" yang dihadapi pada telefon pintar kami. Kami mulakan dengan membuat elemen
video<span>, </span> canvas<span>, </span> context<span>,</span>
Langkah seterusnya adalah untuk benar -benar menarik suapan kamera kami menggunakan pilihan ini. Untuk ini, kami menggunakan API MediaStream. Ini adalah satu set API JavaScript yang membolehkan kami menarik data dari aliran audio dan video tempatan - sesuai untuk mendapatkan aliran kamera telefon kami. Khususnya, kami akan menggunakan fungsi getUsermedia. API MediaStream masih dalam "Draf Editor W3C" dan dilaksanakan sedikit pelayar yang berbeza untuk penyemak imbas. Demo ini difokuskan terutamanya pada Google Chrome untuk mudah alih tetapi untuk keserasian masa depan, kami mendapat yang berfungsi dengan penyemak imbas semasa kami dan memberikannya kepada Navigator.Getusermedia:
themes <span>= ['blackandwhite', 'sepia', 'arcade', 'inverse'], </span> currentTheme <span>= 0, </span> lookingAtGround <span>= false;</span>
Kemudian, selagi penyemak imbas kami memahami MediaStreamTrack dari API MediaStream dan berjaya menemui fungsi getUsermedia yang serasi dalam penyemak imbas kami, kami akan memulakan pencarian kami untuk data kamera.
<span>init(); </span> <span>function init() { </span> scene <span>= new THREE<span>.Scene</span>(); </span> camera <span>= new THREE<span>.PerspectiveCamera</span>(90, window.innerWidth / window.innerHeight, 0.001, 700); </span> camera<span>.position.set(0, 15, 0); </span> scene<span>.add(camera); </span> renderer <span>= new THREE<span>.WebGLRenderer</span>(); </span> element <span>= renderer.domElement; </span> container <span>= document.getElementById('webglviewer'); </span> container<span>.appendChild(element); </span> effect <span>= new THREE<span>.StereoEffect</span>(renderer); </span> element<span>.addEventListener('click', fullscreen, false);</span>
Dalam API MediaStream, kami mempunyai fungsi dalam MediaStreamTrack.GetSources () yang mengambil semua sumber audio dan video yang tersedia untuk penyemak imbas dari perantinya. Ia boleh mendapatkan data mikrofon dari setiap mikrofon yang disambungkan ke peranti anda, bersama dengan data video dari setiap kamera.
Nilai yang dikembalikan dari fungsi ini tersedia untuk kami dalam array yang dipanggil sumber. Kami gelung melalui setiap sumber dan mencari orang yang jenisnya sama dengan "video". Setiap sumber sama ada mempunyai jenis "audio" atau "video". Kami kemudian melihat sama ada video yang dijumpai mempunyai harta yang sama dengan "persekitaran", jika ya, ini adalah kamera yang kami lebih suka menggunakannya. Kami mengambil IDnya dalam API dan kemudian mengemas kini objek Opsyen kami dari sebelumnya untuk juga memasukkan ID sumber ini sebagai aliran video pilihan kami untuk digunakan.
<span>var scene, </span> camera<span>, </span> renderer<span>, </span> element<span>, </span> container<span>, </span> effect<span>,</span>
Objek Opsyen sekarang akan kelihatan seperti di belakang tabir:
video<span>, </span> canvas<span>, </span> context<span>,</span>
Akhirnya, kami lulus dalam pilihan tersebut ke Navigator.GetuserMedia kami berfungsi bersama -sama dengan kejayaan dan panggilan balik ralat. Yang akan melakukan pengambilan data video kami.
themes <span>= ['blackandwhite', 'sepia', 'arcade', 'inverse'], </span> currentTheme <span>= 0, </span> lookingAtGround <span>= false;</span>
Sebaik sahaja kami mempunyai aliran video kami, kami memasukkannya ke dalam adegan kami dalam panggilan balik kejayaan kami, Streamfound (). Kami mulakan dengan menambah elemen video kami ke DOM, menetapkan kandungannya ke aliran video kami yang dikembalikan dan menjadikannya lebar dan ketinggian penuh tetingkap (seperti yang kita mahu resolusi tinggi untuk dibaca ke dalam kanvas kami).
<span>init(); </span> <span>function init() { </span> scene <span>= new THREE<span>.Scene</span>(); </span> camera <span>= new THREE<span>.PerspectiveCamera</span>(90, window.innerWidth / window.innerHeight, 0.001, 700); </span> camera<span>.position.set(0, 15, 0); </span> scene<span>.add(camera); </span> renderer <span>= new THREE<span>.WebGLRenderer</span>(); </span> element <span>= renderer.domElement; </span> container <span>= document.getElementById('webglviewer'); </span> container<span>.appendChild(element); </span> effect <span>= new THREE<span>.StereoEffect</span>(renderer); </span> element<span>.addEventListener('click', fullscreen, false);</span>
Kami menetapkan kanvas kami ke lebar dan ketinggian yang sama seperti video, dibulatkan kepada kuasa terdekat dua. Alasannya ialah tekstur tiga.js berfungsi dengan baik sebagai kuasa 2. Jika anda melewati lebar dan ketinggian lain yang tidak sesuai dengan ini, itu benar -benar baik, tetapi anda perlu menggunakan pilihan minfilter dan magfilter tertentu. Saya lebih suka menyesuaikannya dengan kuasa dua untuk menjaga perkara yang mudah di sini.
<span>if (window.<span>DeviceOrientationEvent</span>) { </span> <span>window.addEventListener('deviceorientation', function(evt) { </span> <span>if (evt.gamma > -1 && evt.gamma < 1 && !lookingAtGround) { </span> lookingAtGround <span>= true; </span> currentTheme <span>= (themes.length > currentTheme+1) ? currentTheme+1 : 0; </span> <span>setTimeout(function() { </span> lookingAtGround <span>= false; </span> <span>}, 4000); </span> <span>} </span> <span>}.bind(this)); </span> <span>}</span>
video <span>= document.createElement('video'); </span> video<span>.setAttribute('autoplay', true); </span> <span>var options = { </span> <span>video: { </span> <span>optional: [{facingMode: "environment"}] </span> <span>} </span> <span>};</span>
<span>navigator.getUserMedia = navigator.getUserMedia || </span> <span>navigator.webkitGetUserMedia || navigator.mozGetUserMedia;</span>
<span>if (typeof MediaStreamTrack === 'undefined' && navigator.getUserMedia) { </span> <span>alert('This browser doesn\'t support this demo :('); </span> <span>} else { </span> <span>// Get our camera data!</span>
<span>MediaStreamTrack.getSources(function(sources) { </span> <span>for (var i = 0; i !== sources.length; ++i) { </span> <span>var source = sources[i]; </span> <span>if (source.kind === 'video') { </span> <span>if (source.facing && source.facing == "environment") { </span> options<span>.video.optional.push({'sourceId': source.id}); </span> <span>} </span> <span>} </span> <span>}</span>
<span>var scene, </span> camera<span>, </span> renderer<span>, </span> element<span>, </span> container<span>, </span> effect<span>,</span>
Fungsi Animate () kami bermula dengan melukis bingkai terkini dari kamera kami ke kanvas kami menggunakan context.drawimage ():
video<span>, </span> canvas<span>, </span> context<span>,</span>
dari sana, kita dapat membaca semula kanvas kita menggunakan context.getimagedata () dan memohon penapis pada data yang dipegangnya bergantung pada tema yang kita tetapkan. Kod di bawah bermula dengan tetapan untuk penapis hitam dan putih kami yang dibaca dalam data kami, mendapat pencahayaan umum setiap piksel dalam imej dan kemudian menapis setiap piksel sama ada hitam, kelabu atau putih bergantung pada skala pencahayaan yang dipegangnya . Ini memberikan akhbar akhbar gaya kartun/lama kepada imej.
themes <span>= ['blackandwhite', 'sepia', 'arcade', 'inverse'], </span> currentTheme <span>= 0, </span> lookingAtGround <span>= false;</span>
yang kelihatan seperti:
Tema seterusnya membalikkan piksel kami, jadi putih hitam dan sebagainya. Ia memberikan gaya X-ray kepada imej:
<span>init(); </span> <span>function init() { </span> scene <span>= new THREE<span>.Scene</span>(); </span> camera <span>= new THREE<span>.PerspectiveCamera</span>(90, window.innerWidth / window.innerHeight, 0.001, 700); </span> camera<span>.position.set(0, 15, 0); </span> scene<span>.add(camera); </span> renderer <span>= new THREE<span>.WebGLRenderer</span>(); </span> element <span>= renderer.domElement; </span> container <span>= document.getElementById('webglviewer'); </span> container<span>.appendChild(element); </span> effect <span>= new THREE<span>.StereoEffect</span>(renderer); </span> element<span>.addEventListener('click', fullscreen, false);</span>
yang kelihatan seperti:
Tema sepia kami menggunakan formula yang saya lihat di pelbagai tempat di web untuk memberikan imej sepia, sekolah berwarna lama. Saya juga menambah bunyi pada imej dengan menambahkan tahap rawak merah, hijau dan biru ke setiap piksel. Sekiranya piksel melalui sepia akan menjadi tahap warna yang lebih besar daripada 255, saya menutupnya pada 255.
<span>if (window.<span>DeviceOrientationEvent</span>) { </span> <span>window.addEventListener('deviceorientation', function(evt) { </span> <span>if (evt.gamma > -1 && evt.gamma < 1 && !lookingAtGround) { </span> lookingAtGround <span>= true; </span> currentTheme <span>= (themes.length > currentTheme+1) ? currentTheme+1 : 0; </span> <span>setTimeout(function() { </span> lookingAtGround <span>= false; </span> <span>}, 4000); </span> <span>} </span> <span>}.bind(this)); </span> <span>}</span>
yang kelihatan seperti:
Akhirnya, kegemaran saya semua kesan! Gaya "Arcade" yang memusingkan imej untuk menjadikannya kelihatan seperti dunia retro. Untuk mencapai kesan ini, saya telah menyesuaikan plugin Pixelate yang rapat oleh David Desandro dan John Schulz. Versi asal plugin menukarkan imej sebaris dan menggantikannya dengan versi kanvas pixelated. Versi saya sebaliknya mengambil data kanvas dan meletakkannya kembali ke kanvas dan konteks yang sama, jadi kita boleh menggunakannya untuk video langsung. Versi diselaraskan saya masih menerima semua parameter yang sama seperti yang ada di halaman plugin mereka. Ia agak lebih perlahan daripada penapis lain di atas dan berpotensi dioptimumkan jika saya mendapat masa untuk melihatnya. Buat masa ini, saya baik -baik saja dengan sedikit lag, menjadikannya lebih retro! Nota bagi sesiapa sahaja yang kelihatan menggunakan pilihan baru ke dalam penapis itu (mis. Mengubah dunia menjadi berlian) - ia boleh menjadikannya lebih banyak lagi!
video <span>= document.createElement('video'); </span> video<span>.setAttribute('autoplay', true); </span> <span>var options = { </span> <span>video: { </span> <span>optional: [{facingMode: "environment"}] </span> <span>} </span> <span>};</span>
yang kelihatan seperti:
Akhirnya, kami menetapkan tekstur untuk mengemaskini bingkai seterusnya untuk tiga.js (seperti yang telah kami ubah dalam beberapa cara) dan berjalan Animate () sekali lagi pada permintaan yang akan datang (). Kami juga menjalankan kod untuk mengemas kini dan menyusun semula adegan tiga.js kami.
<span>var scene, </span> camera<span>, </span> renderer<span>, </span> element<span>, </span> container<span>, </span> effect<span>,</span>
Kemas kini pada akhir tahun 2015 - Saya melompat kembali ke artikel ini untuk menambah sedikit maklumat yang agak penting - Chrome kini memerlukan halaman web yang menggunakan kamera dihidangkan melalui HTTPS. Jadi sebelum cuba menjalankan ini, anda perlu mencari cara untuk menjalankan perkhidmatan anda melalui HTTPS. Satu kaedah yang saya gunakan setakat ini untuk ujian adalah NGROK, yang boleh menyediakan terowong HTTPS ke localhost anda. Kami mempunyai panduan untuk mengakses localhost dari mana saja di SitePoint yang dapat membantu anda memulakan.
Untuk dapat mengakses webcam dan semua, nampaknya anda perlu menjadi tuan rumah pada pelayan dan bukannya menjalankannya secara tempatan. Untuk tujuan ujian, saya menggunakan NGROK untuk menguji dari Mac saya di telefon saya. Jika tidak, FTP barangan anda ke pelayan web di suatu tempat dan uji!
Jalankannya di dalam kadbod Google anda atau alat dengar VR yang lain dan anda harus melihat persekitaran di sekeliling anda dengan penapis hitam dan putih kami untuk bermula dengan. Jika anda melihat ke bawah di tanah, ia harus menukar penapis. Ia sangat menyeronokkan! Berikut adalah gif animasi kecil untuk menunjukkannya dalam tindakan (di luar alat dengar supaya anda dapat melihat apa yang dipaparkan):
Menggabungkan kuasa Google Cardboard, HTML5, JavaScript dan Three.js membawa beberapa kemungkinan yang benar -benar kemas yang tidak semata -mata terhad kepada realiti maya. Menggunakan input kamera, anda boleh membawa dunia di sekeliling anda ke tempat kejadian juga! Terdapat banyak bidang lain idea awal ini boleh dibangunkan. Ia juga mungkin untuk menapis imej melalui tiga.js sendiri menggunakan shaders dan mungkin untuk menambah objek realiti tambahan ke tempat kejadian anda - dua idea yang saya akan tutupi dalam artikel masa depan.
Jika anda membuat beberapa pengalaman yang benar -benar kemas berdasarkan demo ini, tinggalkan nota dalam komen atau berhubung dengan saya di Twitter (@thatpatrickguy), saya sentiasa berminat untuk melihat!
Properti 'Filter' dalam JavaScript digunakan untuk menetapkan atau mengembalikan penapis yang digunakan untuk elemen. Ini termasuk perkara-perkara seperti kabur, kecerahan, kontras, skala kelabu, hue-rotate, invert, kelegapan, tepu, sepia, dan banyak lagi. Ia boleh digunakan untuk membuat pelbagai kesan visual di laman web anda. Unsur -unsur AR, seperti bagaimana mereka bergerak, bertindak balas terhadap input pengguna, atau berubah dari masa ke masa. Perpustakaan seperti ar.js dapat memudahkan proses ini, membolehkan anda membuat pengalaman AR dengan hanya beberapa baris kod.
Google Cardboard direka terutamanya untuk pengalaman VR, tetapi ia juga boleh digunakan untuk AR dengan perisian yang betul. Anda boleh menggunakan JavaScript bersama dengan API WebVR untuk mencipta pengalaman AR untuk Google Cardboard.
Atas ialah kandungan terperinci Menapis Realiti dengan JavaScript dan Google Cardboard. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!