Die Fähigkeit, die virtuelle Realität innerhalb eines mobilen Browsers durchzuführen, ist ermächtig und aufregend. Google Cardboard und andere ähnliche VR -Geräte machen es unglaublich einfach, legen Sie Ihr Telefon einfach in den Halter und gehen Sie! Ich habe zuvor mit Google Cardboard und drei.js VR ins Web gebracht, wo ich die Grundlagen des Aufbaus einer VR -Umgebung erörterte, die Webdaten einzieht. Die Leute haben diesen Artikel wirklich genossen (und ich habe es wirklich genossen, diese Demo zu bauen), also dachte ich, ich würde ihn mit einer anderen Idee erweitern. Anstatt Web -APIs einzubringen, bringen Sie nicht die Kamera Ihres Telefons ein und verwandeln Sie dies in ein erweitertes Reality -Erlebnis?
In diesem Artikel werde ich untersuchen, wie wir Kameradaten einziehen, sie filtern und mit HTML5 und JavaScript wieder anzeigen können. Wir werden dies alles durch einen stereoskopischen Sehvermögen tun, um ein Augmented Reality -Erlebnis für Google Cardboard und andere VR -Geräte zu schaffen. Wir werden ein paar verschiedene Filter auf unseren Kamera -Stream anwenden
Wenn Sie mit HTML5, dem Canvas -Tag und JavaScript völlig neu für Filterbilder sind, habe ich einen ganzen Kurs zum Thema bei Lernable Called JavaScript in Motion! Ich werde mich diesem Artikel mit der Annahme nähern, dass Sie die Leinwand- und Video -Tags verstehen, zusammen mit dem Streamen von Videos in das Canvas -Tag. Oder mit der Annahme, dass Sie zuversichtlich genug sind, es zu erarbeiten, wenn Sie gehen!Demo -Code
Möchten Sie es in Aktion versuchen? Ich habe hier eine laufende Version gehostet: Reality Filter.
Hinweis: Eine kürzlich durchgeführte Änderung in der Art und Weise, wie die Chromeingabe der Kamera mit der Seite mit HTTPS ausgeführt wird, muss dies funktionieren!
wir werden den gleichen ersten Einricht aus dem vorherigen Google Cardboard -Artikel einnehmen - eine drei.js -Szene, die wir durch einen stereoskopischen Effekt anzeigen. Dieser Effekt ermöglicht es uns, für jedes Auge ein Display zu haben und die Dinge in VR wunderbar 3D aussehen zu lassen. Anstatt jedoch Partikel und dergleichen aus dem vorherigen Artikel zu schweben, entfernen wir die meisten Elemente und platzieren ein einfaches drei.js -Netz vor der Kamera, die unseren Kamera -Feed spielt.
Wenn wir unsere variablen Erklärungen betrachten, sehen die meisten Variablen hier denjenigen bekannt aus, die die vorherige Demo durchlaufen haben. Die Variablen für die Vorbereitung unserer drei.js -Szene, der Kamera, des Renderers, des Elements für unsere Leinwandausgabe, Container, um dieses Element zu platzieren, und eine Variable, um unseren stereoskopischen Effekt zu speichern, sind alle gleich.
<span>var scene, </span> camera<span>, </span> renderer<span>, </span> element<span>, </span> container<span>, </span> effect<span>,</span>
Unsere drei neuen Variablen, die sich auf unseren Kamera -Feed beziehen, sind Video, Leinwand und Kontext.
video<span>, </span> canvas<span>, </span> context<span>,</span>
Wir haben einige andere Variablen unter denen, die sich auf unsere Filterfunktionalität beziehen.
themes <span>= ['blackandwhite', 'sepia', 'arcade', 'inverse'], </span> currentTheme <span>= 0, </span> lookingAtGround <span>= false;</span>
Wir beginnen mit unserer Init () -Funktion, die unsere Szene, unsere Kamera usw. wie zuvor einrichten:
<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>
Wir haben diesmal keine Kamerabewegungsfunktionalität über das Geräteereignis. Im Vergleich zu einer VR -Erfahrung müssen wir die tatsächliche Kameraposition in dieser drei.js -Szene nicht ändern. Wir halten die Szene an derselben Stelle - der Kamera -Feed ist das, was sich bewegt, wenn sich der Benutzer umsieht.
Ein Hörer, den wir vom vorherigen Beispiel gehalten haben, ist ein Ereignishörer, um das Vollbild zu gehen, wenn wir auf die Szene tippen. Dadurch wird die Chromadressleiste aus unserer Ansicht entfernt.
Es gibt eine neue Verwendung für den Geräte -Unternehmen in dieser Demo. Wir setzen es so, dass wir nach Änderungen in der Ausrichtung unseres Geräts achten und dies als Auslöser für das Umschalten unseres Filters verwenden. Wir haben keine physischen Steuerelemente, um Ereignisse auszulösen. Daher steuern wir die Dinge, an denen der Benutzer sucht. Insbesondere ändern wir den Filter, wenn der Benutzer den Boden betrachtet.
<span>var scene, </span> camera<span>, </span> renderer<span>, </span> element<span>, </span> container<span>, </span> effect<span>,</span>
In diesem Code beobachten wir, ob die EVT.Gamma zwischen -1 und 1. liegt. Wenn ja, schauen sie auf den Boden. Dies ist ein genauer Punkt auf dem Boden. Wenn Sie es zu klein und schwer auszulösen, können Sie den Bereich auf -1,5 und 1,5… usw. erhöhen
Wenn sie in diesem Bereich suchen und wenn das Schauen von Suchgur falsch ist, führen wir unseren Themen -Switcher -Code aus. Dies passt das aktuelle Gesamtwert an die nächste Indexnummer unseres Themenarrays. Wir haben den Lookatplatz auf True gesetzt und nach 4 Sekunden zurückgestellt. Dies stellt sicher, dass wir den Filter nur alle vier Sekunden ändern.
Um die Welt um uns herum zu filtern, benötigen wir Zugang zur „Umgebung“, mit der die Kamera auf unserem Smartphone ausgerichtet ist. Wir erstellen zunächst ein
video<span>, </span> canvas<span>, </span> context<span>,</span>
Unser nächster Schritt besteht darin, mit diesen Optionen unseren Kamera -Feed tatsächlich einzuziehen. Dafür verwenden wir die Medienstream -API. Dies ist eine Reihe von JavaScript -APIs, mit denen wir Daten aus lokalen Audio- und Video -Streams ziehen können - perfekt für den Kamera -Stream unseres Telefons. Insbesondere verwenden wir die GetUsMedia -Funktion. Die MediaStream -API befindet sich noch im Entwurf des W3C -Editors und wird etwas anders im Browser implementiert. Diese Demo konzentriert sich hauptsächlich auf Google Chrome für Mobilgeräte, aber für zukünftige Kompatibilitätssech
themes <span>= ['blackandwhite', 'sepia', 'arcade', 'inverse'], </span> currentTheme <span>= 0, </span> lookingAtGround <span>= false;</span>
<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>
Die zurückgegebenen Werte dieser Funktion stehen uns in einem Array namens Quellen zur Verfügung. Wir durchlaufen jede Quelle und suchen nach denen, deren Art dem "Video" entspricht. Jede Quelle hat entweder eine Art "Audio" oder "Video". Wir sehen dann, ob das gefundene Video über eine Gesichtseigenschaft verfügt, die der "Umgebung" entspricht. Wenn ja, ist dies die Kamera, die wir lieber verwenden würden. Wir rufen seine ID in der API ab und aktualisieren dann unser Optionsobjekt von früher, um diese Quell -ID auch als unseren bevorzugten Video -Stream einzuschließen.
<span>var scene, </span> camera<span>, </span> renderer<span>, </span> element<span>, </span> container<span>, </span> effect<span>,</span>
Das Optionsobjekt würde jetzt wie hinter den Kulissen aussehen:
video<span>, </span> canvas<span>, </span> context<span>,</span>
Schließlich geben wir diese Optionen an unseren Navigator.getUlermedia -Funktion zusammen mit einem Erfolgs- und Fehler -Rückruf weiter. Das wird das Abrufen unserer Videodaten erledigen.
themes <span>= ['blackandwhite', 'sepia', 'arcade', 'inverse'], </span> currentTheme <span>= 0, </span> lookingAtGround <span>= false;</span>
Sobald wir unseren Video -Stream haben, haben wir ihn in unserem Erfolgs -Rückruf streamFound () in unsere Szene gesteckt. Wir fügen zunächst unser Videoelement zum DOM hinzu, setzen seinen Inhalt in unseren zurückgegebenen Video -Stream und machen es die volle Breite und Höhe des Fensters (da wir eine hohe Auflösung in unsere Leinwand lesen möchten).
<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>
Nachdem wir unseren Kamera -Stream auf der Seite gespielt haben, erstellen wir ein Canvas -Element in JavaScript, mit dem wir die Manipulation unserer Videodaten durchführen. Das Canvas -Element selbst wird nie in die Seite selbst hinzugefügt, es bleibt nur in unserem JavaScript.
Wir setzen unsere Leinwand auf die gleiche Breite und Höhe wie das Video, das auf die nächste Leistung von zwei gerundet ist. Der Grund dafür ist, dass drei.js -Texturen am besten als Kräfte von 2. funktionieren. Wenn Sie andere Breiten und Höhen übergeben, die nicht diesem entsprechen, ist das völlig in Ordnung, aber Sie müssen bestimmte Minfilter- und MagFilter -Optionen verwenden. Ich zog es vor, es an die Kraft von zwei anzupassen, um die Dinge hier einfach zu halten.
<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>
Als nächstes erstellen wir unsere drei.js -Textur, die unser Streaming -Video -Filmmaterial enthalten und unser Canvas -Element darin übergeben. Wir setzen unsere Kontextvariable auf den Kontext unseres erstellten Canvas -Elements und weisen den Kontext unserer Textur dem Kontext unserer Leinwand zu. Alles in Synchronisation halten
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>
Wir erstellen dann die drei.js -Ebene. Wir werden unsere Feeds mit drei.PlaneGeometrie aufstellen. Ich habe es 1920 × 1280 als Basisgröße für unser Video eingestellt.
<span>navigator.getUserMedia = navigator.getUserMedia || </span> <span>navigator.webkitGetUserMedia || navigator.mozGetUserMedia;</span>
Dann erstellen wir ein Drei -Mesh -Objekt mit unserer Ebene und unserer Textur mit unserem Video -Feed. Wir positionieren es -600 auf der Z -Achse, bewegen es von unserem Sichtfeld weg und fügen es in unsere drei.js -Szene hinzu. Wenn Sie einen Video -Feed mit unterschiedlicher Größe haben, müssen Sie möglicherweise die Z -Position einstellen, um sicherzustellen, dass die Form das Ansichtsfenster füllt.
<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>
Danach haben wir unsere Fehlerrückruffunktion, die eine Konsole ausführt, wenn etwas mit unserem Video -Stream -Abruf nicht stimmt.
<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>
Am Ende unserer Init () -Funktion sehen Sie unsere Animate () -Funktion. Hier führen wir unsere Verarbeitung des Videobilds durch:
<span>var scene, </span> camera<span>, </span> renderer<span>, </span> element<span>, </span> container<span>, </span> effect<span>,</span>
Unsere Animate () -Funktion beginnt mit dem Zeichnen des neuesten Rahmens von unserer Kamera auf unsere Leinwand mit Context.drawimage ():
video<span>, </span> canvas<span>, </span> context<span>,</span>
Von dort aus können wir unsere Leinwand mit context.getImagedata () () () () zurücklesen und Filter auf die Daten anwenden, die sie je nach dem Thema festlegen. Der folgende Code beginnt mit den Einstellungen für unseren Schwarzweißfilter, der in unseren Daten liest, erhält die allgemeine Luminanz jedes Pixels im Bild und filter . Dies verleiht dem Bild eine Zeitung in Cartoony/Old Style.
themes <span>= ['blackandwhite', 'sepia', 'arcade', 'inverse'], </span> currentTheme <span>= 0, </span> lookingAtGround <span>= false;</span>
das sieht so aus:
Das nächste Thema dreht unsere Pixel um, also ist weiß schwarz und so weiter. Es gibt dem Bild einen Röntgenstil:
<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>
das sieht so aus:
Unser Sepia -Thema verwendet eine Formel, die ich an verschiedenen Orten im Internet gesehen habe, um dem Bild ein SEPIA, ein altschool -farbiges Gefühl zu vermitteln. Ich füge dem Bild auch Rauschen hinzu, indem ich jedem Pixel einen zufälligen Pegel von Rot, Grün und Blau hinzugefügt habe. Wenn die Pixel über SEPIA größere Farbpegel als 255 sein werden, caine ich es bei 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>
das sieht so aus:
schließlich mein Favorit aller Effekte! Der Stil „Arcade“, der das Bild pixelt, damit es wie eine Retro -Welt aussieht. Um diesen Effekt zu erzielen, habe ich das enge Pixelate -Plugin von David Desandro und John Schulz angepasst. Die Originalversion des Plugins konvertiert ein Inline -Bild und ersetzt es durch eine pixelige Leinwandversion. Meine Version nimmt stattdessen Canvas -Daten und bringt sie wieder in die gleiche Leinwand und denselben Kontext, sodass wir sie für Live -Videos verwenden können. Meine angepasste Version akzeptiert immer noch die gleichen Parameter wie die auf ihrer Plugin -Seite. Es ist etwas langsamer als die anderen Filter oben und kann möglicherweise optimiert werden, wenn ich Zeit habe, mich damit zu prüfen. Im Moment bin ich mit ein bisschen Verzögerung einverstanden und macht es sich retro mehr an! Ein Hinweis für alle, die neue Optionen in diesen Filter anwenden möchten (z. B. stattdessen die Welt in Diamanten verwandeln) - es kann ihn noch mehr verzögern!
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>
das sieht so aus:
Schließlich setzen wir die Textur, um den nächsten Frame für drei.Js zu aktualisieren (wie wir sie definitiv in irgendeiner Weise geändert haben) und leiten Animate () bei der nächsten RequestArimationFrame () erneut aus. Wir führen auch Code aus, um unsere drei.js -Szene zu aktualisieren und neu zu gestalten.
<span>var scene, </span> camera<span>, </span> renderer<span>, </span> element<span>, </span> container<span>, </span> effect<span>,</span>
Update Ende 2015 - Ich springe in diesen Artikel zurück, um ein neues Stück ziemlich wichtige Informationen hinzuzufügen - Chrome erfordert jetzt, dass Webseiten mit der Kamera über HTTPS serviert werden. Bevor Sie versuchen, dies auszuführen, müssen Sie einen Weg finden, Ihren Service über HTTPS auszuführen. Eine Methode, die ich bisher zum Testen verwendet habe, ist NGROK, mit dem Sie Ihrem örtlichen Haus einen HTTPS -Tunnel bereitstellen können. Wir haben einen Leitfaden beim Zugriff auf Localhost von überall hier bei SitePoint, der Ihnen helfen kann, den Einstieg zu erlangen.
Um auf die Webcam und alle zugreifen zu können, müssen Sie sie auf einem Server gehostet haben, anstatt sie lokal auszuführen. Zu den Testzwecken habe ich NGROK verwendet, um von meinem Mac auf meinem Telefon zu testen. Ansonsten ftp Ihre Sachen irgendwo auf einen Webserver und testen Sie!
Führen Sie es in Ihrem Google Cardboard oder einem anderen VR -Headset aus und Sie sollten die Umgebung um Sie herum mit unserem Schwarzweißfilter sehen. Wenn Sie auf den Boden nach unten schauen, sollte es Filter wechseln. Es macht viel Spaß! Hier ist ein kleines animiertes GIF, das es in Aktion zeigt (außerhalb des Headsets, damit Sie sehen können, was es zeigt):
kombiniert die Leistung von Google Cardboard, HTML5, JavaScript und Three.js bietet einige wirklich nette Möglichkeiten, die nicht nur auf die virtuelle Realität beschränkt sind. Mit der Kameraeingabe können Sie die Welt auch um Sie herum in die Szene bringen! Es gibt viele andere Bereiche, in denen diese anfängliche Idee entwickelt werden kann. Es ist auch möglich, das Bild über drei.js selbst mit Shader zu filtern und Augmented -Reality -Objekte zu Ihrer Szene hinzuzufügen - zwei Ideen, die ich in zukünftigen Artikeln behandeln werde.
Wenn Sie einige wirklich nette AR -Erlebnisse machen, die auf dieser Demo basieren, in den Kommentaren eine Notiz hinterlassen oder auf Twitter (@thatpatrickGuy) mit mir in Verbindung setzen, bin ich immer sehr daran interessiert, einen Blick darauf zu werfen!
Kann ich eine webbasierte AR-Anwendung mit nur HTML? Während HTML für die Strukturierung des Inhalts einer Webseite von entscheidender Bedeutung ist, kann es allein keine AR -Anwendung erstellen. Sie müssen JavaScript und möglicherweise andere Bibliotheken verwenden, um die AR -Funktionalität zu verarbeiten. Bibliotheken wie AR.JS können diesen Prozess jedoch viel einfacher machen, sodass Sie AR -Erlebnisse mit nur wenigen Codezeilen erstellen können. > Es gibt viele potenzielle Anwendungsfälle für die Integration von HTML5 in AR. Sie können beispielsweise eine AR -Einkaufs -App erstellen, mit der Benutzer vor dem Kauf in ihrem Haus aussehen können. Oder Sie können eine Bildungs-App erstellen, die Informationen über reale Objekte überlagert und den Schülern hilft, auf interaktivere Weise zu lernen. Während HTML für die Strukturierung des Inhalts einer Webseite von entscheidender Bedeutung ist, kann es allein keine AR -Anwendung erstellen. Sie müssen JavaScript und möglicherweise andere Bibliotheken verwenden, um die AR -Funktionalität zu verarbeiten. Bibliotheken wie AR.JS können diesen Prozess jedoch viel einfacher machen, sodass Sie AR -Erfahrungen mit nur wenigen Codezeilen erstellen können.
Wie kann ich JavaScript verwenden, um AR -Erlebnisse zu erstellen? AR -Elemente, wie sie sich bewegen, auf Benutzereingaben reagieren oder sich im Laufe der Zeit ändern. Bibliotheken wie Ar.js können diesen Prozess vereinfachen und ermöglichen Ihnen, AR -Erlebnisse mit nur wenigen Codezeilen zu erstellen.
Das obige ist der detaillierte Inhalt vonFilterung der Realität mit JavaScript und Google Cardboard. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!