Erstellen von 3D-Welten mit HTML und CSS von Keith Clark
Im vergangenen Jahr habe ich eine Demo zeigt, wie CSS 3D-Transformationen 3D-Umgebungen erstellen verwendet werden könnten. Die Demo war eine technische Schaufenster, was zu der Zeit mit CSS erreicht werden könnte, aber ich wollte weit sehen, wie ich die Dinge drücken könnte, so in den letzten paar Monaten habe ich an einer neuen Version arbeiten mit komplexeren Modellen, realistische Beleuchtung habe , Schatten und Kollisionserkennung. Dieser Beitrag dokumentiert, wie ich tat es und die Techniken, die ich verwendet.
Erstellen von 3D-Objekten
In der heutigen 3D-Engines eine Objekte Geometrie wird als eine Ansammlung von Punkten gespeichert (oder Ecken), die jeweils mit einer x. y und z-Eigenschaft, die seine Position im 3D-Raum festlegt. Ein Rechteck würde beispielsweise durch vier Scheitelpunkte, eine für jede Ecke definiert werden. Jede Ecke kann individuell manipuliert werden, so dass das Rechteck in verschiedene Formen durch Bewegen seiner Ecken entlang der X-, Y- und Z-Achse gezogen wird. Die 3D-Engine wird diese Vertex-Daten verwenden und einige clevere mathematische 3D-Objekte auf dem 2D-Bildschirm zu machen.
Mit CSS wandelt diese auf den Kopf gestellt wird. Wir können nicht beliebige Formen unter Verwendung einer Reihe von Punkten definieren, sind wir mit HTML-Elementen fest, die immer rechteckig sind und zweidimensionale Eigenschaften wie oben. links. Breite und Höhe ihrer Position und Größe zu bestimmen. In vielerlei Hinsicht macht dies einfacher mit 3D zu tun, da es keine komplexe Mathematik ist zu behandeln - gilt nur ein CSS-Transformation ein Element um eine Achse zu drehen und du bist fertig!
Erstellen von Objekten aus Rechtecke scheinen zunächst zu begrenzen, aber man kann mit ihnen überraschend viel zu tun, vor allem, wenn Sie mit PNG Alpha-Kanälen zu spielen beginnen. Im Bild unten können Sie obwohl sie sich aus Rechtecke sehen scheinen die Faßdeckel und Rad Objekte abgerundet.
Das folgende Beispiel zeigt dies in der Praxis - einen Blick auf die „JS“ Tab haben:
Eine 3D-Öltrommel gebaut unter Verwendung von rechteckigen
Die Beleuchtung war die größte Herausforderung in diesem Projekt. Ich will nicht lügen, die Mathematik mich fast brach, aber es war die Mühe wert, weil Beleuchtung einer sonst flach und leblos Umgebung ein unglaubliches Gefühl von Tiefe und Atmosphäre bringt.
Wie ich bereits erwähnt, wird ein Objekt in Ihrer durchschnittlichen 3D-Engine durch eine Reihe von Eckpunkten definiert. Zur Berechnung dieser Eckpunkte Beleuchtung verwendet, um einen „normalen“ zu berechnen, die verwendet werden können, um zu bestimmen, wie viel Licht auf den Mittelpunkt einer Oberfläche treffen. Dies stellt ein Problem dar, wenn 3D-Objekte mit HTML-Elementen erstellen, da diese Vertexdaten nicht existieren. So war die erste Herausforderung darin, eine Reihe von Funktionen zu schreiben, um die vier Ecken (ein für jede Ecke) für ein Element zu berechnen, die mit CSS umgewandelt worden war, so dass die Beleuchtung berechnet werden kann. Sobald das wurde herausgefunden begann ich mit verschiedenen Möglichkeiten, um Lichtobjekte zu experimentieren. In meinem ersten Versuch habe ich mehr background-image s Licht zu simulieren, eine Oberfläche trifft durch einen linearen Gradienten mit einem Bild kombiniert. Der Effekt verwendet ein Gradient und endet mit dem gleichen RGBA-Wert beginnt, einen festen Block der Farbe erzeugt. den Wert des Alphakanal variierende ermöglicht das darunter liegende Bild durch den Farbblock bluten die Illusion von Abschattung zu schaffen.
den zweiten dunkelsten Effekt im Bild oben zu erreichen, habe ich die folgenden Arten auf ein Element anwenden:
Eine flache schattierte 3D Öltrommel
Diese Technik wird als Schattierung bezeichnet. Es ist eine wirksame Methode zur Beschattung, aber es ist in der gesamten Oberfläche führt das gleiche Detail mit. wenn ich eine 3D-Wand erstellt zum Beispiel, die in die Ferne erweitert, wäre es gleich auf seiner gesamten Länge beschattet werden. Ich wollte etwas, das mehr realistisch aussah.
Ein zweiter Stich bei Beleuchtung
Um echte Beleuchtung zu simulieren, müssen Oberflächen verdunkeln, da sie über den Bereich einer Lichtquelle erstrecken, und wenn mehrere Lichter die gleiche Oberfläche treffen sollte es Schatten entsprechend.
Ich kann so bestimmen, wie hell oder dunkel jeder Punkt sein sollte, um eine Oberfläche zu flach Schatten Ich hatte nur das Licht berechnen den Mittelpunkt schlagen, aber jetzt brauche ich an verschiedenen Stellen auf der Oberfläche das Licht zu probieren. Die Mathematik erforderlich, um diese Beleuchtungsdaten zu erstellen, ist identisch mit dem für Schattierung verwendet.
Die Lösung war eine verwenden,
Die Hintergrund Stilregel für eine Licht Karte und Textur auf eine Oberfläche sieht ungefähr so aus:
Welche erzeugt die endgültige beleuchtete Oberfläche:
Casting Shadows
Einschwingzeit auf Leinwand für die Beleuchtung aus Schatten möglich Gießen. Die Logik hinter drehte Schattenwurf aus ziemlich einfach zu sein. Bestellflächen auf der Grundlage ihrer Nähe zu einer Lichtquelle erlaubte mich nicht nur eine Licht Karte für eine Oberfläche zu erzeugen, sondern auch bestimmen, ob eine vorherige Oberfläche bereits von dem aktuellen Lichtstrahl getroffen worden war. Wenn es hat, konnte ich die entsprechende Licht Karte Pixel gesetzt im Schatten zu sein. Diese Technik ermöglicht ein Bild sowohl für Beleuchtung und Schatten verwendet.
Collisions
Kollisionserkennung verwendet eine Höhenkarte - eine Top-down-Bild von der Ebene, die Farbe, um die Höhe der in ihr enthaltenen Objekte darzustellen verwendet. Weiß steht für die tiefste und schwarz die höchstmögliche Position der Spieler erreichen kann. Da die Spieler bewegt sich um die Ebene konvertiere ich ihre Position in 2D-Koordinaten und nutzen sie, um die Farbe in der Höhenkarte zu überprüfen. Wenn die Farbe letzte Position ist leichter als die Spieler der Spieler fällt, wenn es leicht ist dunkler kann der Spieler verstärken oder zu einem Objekt springt auf. Wenn die Farbe viel dunkler der Spieler zu einem Anschlag kommt, ist - ich benutze diese für Wände und Zäune. Derzeit wird dieses Bild von Hand gezeichnet, aber ich werde in suche sie dynamisch zu schaffen.
Was kommt als nächstes?
Nun, ein Spiel wäre ein natürlicher nächster Schritt für dieses Projekt sein - es wäre interessant zu sehen, wie skalierbar ist diese Techniken. Arbeit an einem Prototyp CSS3-Renderer für die ausgezeichneten Three.js Auf kurze Sicht, ich habe angefangen, die diese gleichen Techniken verwendet Geometrie und Licht von einem echten 3D-Engine erstellt zu machen.
Schon einmal daran gedacht traditionellen FPS Collider Ansatzes (Ellipsoid gegen Ebene Tests) für die Kollision der Verwendung? Wenn Sie konvexe Feststoffe / Testen von Zellen sind gegen, können Sie so lange eine mögliche Kollision auszuschließen, da es keine der gegebenen Ebenen durch den konvexen gebildete Feststoff berührt. Die Beleuchtung ist allerdings wirklich gut.
Irgendwie ist das mousemove- Detektionsereignis nicht scheint gut auf meiner Version von Safari zu arbeiten. Betrachtet mit Hilfe eines Drag-Controller wie das, was ich für meine fps Demos tat? Mein Drag-Controller funktioniert auch auf mobilen, weil ich Hammer.js api bin mit. Allerdings ist in Bezug auf Leistung / features / Speichergrenzen nicht einfach etwas auf Handy haben. Die besten Anwendungen sind einige Cubic VR und einig 3D-Geometrie oder eine einfache 3D-Geometrie in einem einzigen Raum.
Äußerst beeindruckend, Keith! Halten Sie die großartige Arbeit.
Großes Experiment! Auf der letzten stabilen Version von Chrome noch (Version 24.0.1312.56) läuft unter Linux, ist Ihre Demo voll functionnal aber Modelle sind Clipping während der Bewegung.
Gute Arbeit in jedem Fall sehr interessant!
Leider von Clipping-Probleme Chrome leidet. Ich habe dies dokumentiert, zusammen mit Ausgaben in anderen Browsern in einem frühen Blog-Beitrag