Dieser Artikel ist eine Fortsetzung der Grundlagen der Formate GLTF und GLB. Den ersten Teil des Artikels finden Sie hier . Im ersten Teil haben wir mit Ihnen untersucht, warum das Format ursprünglich geplant war, sowie Artefakte und deren Attribute des GLTF-Formats wie Szene, Knoten, Puffer, Pufferansicht, Accessor und Netz. In diesem Artikel werden wir Material, Textur, Animationen, Haut, Kamera betrachten und die Erstellung einer minimal gültigen GLTF-Datei abschließen.

Material und Textur
Materialien und Texturen sind untrennbar mit dem Netz verbunden. Bei Bedarf kann das Netz animiert werden. Das Material speichert Informationen darüber, wie das Modell von der Engine gerendert wird. GLTF definiert Materialien mithilfe eines gemeinsamen Parametersatzes, der auf Physical-Based Rendering (PBR) basiert. Mit dem PBR-Modell können Sie eine „physikalisch korrekte“ Anzeige des Objekts unter verschiedenen Lichtbedingungen erstellen, da das Schattierungsmodell mit den „physikalischen“ Oberflächeneigenschaften arbeiten muss. Es gibt verschiedene Möglichkeiten, PBR zu beschreiben. Das gebräuchlichste Modell ist das Metallrauheitsmodell, das standardmäßig in GLTF verwendet wird. Sie können auch das Spiegelglanzmodell verwenden, jedoch nur mit einer separaten Erweiterung (Erweiterung). Die Hauptattribute des Materials sind wie folgt:
- name ist der Name des Netzes.
- baseColorFactor / baseColorTexture - speichert Farbinformationen. Im Fall des Faktorattributs werden Informationen in einem numerischen Wert für RGBA gespeichert, im Fall von Textur wird die Texturreferenz im Texturobjekt gespeichert.
- metallicFactor - speichert metallische Informationen
- roughnessFactor - speichert Informationen zur Rauheit
- doubleSided - true oder false (der Standardwert) und gibt an, ob das Netz auf beiden Seiten oder nur auf der "Vorderseite" gerendert wird.
"materials": [ { "pbrMetallicRoughness": { "baseColorTexture": { "index": 0 }, "metallicFactor": 0.0, "roughnessFactor": 0.800000011920929 }, "name": "Nightshade_MAT", "doubleSided": true } ],
Metallisch oder die Bedeutung von „Metallizität“. Dieser Parameter beschreibt, wie stark es ähnlich wie echtes Metall reflektiert, d.h. wie viel Licht von der Oberfläche reflektiert wird. Der Wert wird von 0 bis 1 gemessen, wobei 0 ein Dielektrikum und 1 ein reines Metall ist.
Rauheit oder "Rauheit". Dieses Attribut zeigt an, wie „rau“ die Oberfläche ist, wodurch die Streuung von Licht von der Oberfläche beeinflusst wird. Gemessen von 0 bis 1, wobei 0 vollkommen flach ist und 1 eine völlig raue Oberfläche ist, die nur eine geringe Lichtmenge reflektiert.
Textur - Ein Objekt, das Texturkarten (Texturkarten) speichert. Solche Karten geben ein realistisches Modell. Dank ihnen können Sie das Erscheinungsbild des Modells bestimmen, um verschiedene Eigenschaften wie Metallizität, Rauheit, natürliche Verdunkelung der Umgebung und sogar die Eigenschaften des Glühens zu erhalten. Texturen werden durch drei übergeordnete Arrays beschrieben: Texturen, Sampler, Bilder. Das Textures-Objekt verwendet Indizes, um auf Sampler- und Bildinstanzen zu verweisen. Das wichtigste Objekt ist das Bild, weil Er ist es, der die Standortinformationen der Karte speichert. In Texturen wird es durch die Wortquelle beschrieben. Das Bild befindet sich möglicherweise irgendwo auf der Festplatte (z. B. "uri": "duckCM.png") oder ist in GLTF codiert ("bufferView": 14, "mimeType": "image / jpeg"). Sampler ist ein Objekt, das Filter- und Umbruchparameter definiert, die GL-Typen entsprechen.
In unserem Dreiecksbeispiel gibt es keine Texturen, aber ich werde JSON von anderen Modellen geben, mit denen ich gearbeitet habe. In diesem Beispiel wurden die Texturen in den Puffer geschrieben, sodass sie auch mit BufferView aus dem Puffer gelesen werden:
"textures": [ { "sampler": 0, "source": 0 } ], "images": [ { "bufferView": 1, "mimeType": "image/jpeg" } ],
Animationen
GLTF unterstützt artikulierte, gehäutete und verwandelte Zielanimationen mithilfe von Keyframes. Die Informationen dieser Frames werden in Puffern gespeichert und beziehen sich auf Animationen mit Accessoren. GLTF 2.0 definiert nur den Animationsspeicher, definiert also kein bestimmtes Laufzeitverhalten wie Wiedergabereihenfolge, Autoplay, Loops, Timeline-Anzeige usw. Alle Animationen werden im Animations-Array gespeichert und als Set definiert Kanäle (Kanalattribut) sowie eine Reihe von Abtastwerten, die von Accessoren bestimmt werden, die Informationen über Schlüsselrahmen und die Interpolationsmethode (Abtastattribut) verarbeiten
Die Hauptattribute des Animationsobjekts lauten wie folgt:
- name - Name der Animation (falls vorhanden)
- channel - Ein Array, das die Ausgabewerte der Keyframes der Animation mit einem bestimmten Knoten in der Hierarchie verbindet.
- Sampler ist ein Attribut, das sich auf Accessor bezieht, das Schlüsselbilder aus dem Puffer verarbeitet.
- Ziel ist ein Objekt, das bestimmt, welcher Knoten (Knotenobjekt) mithilfe des Knotenattributs animiert werden muss und welche Eigenschaft des Knotens mithilfe des Pfadattributs animiert werden muss - Übersetzung, Drehung, Skalierung, Gewichte usw. Nicht animierte Attribute behalten ihre Werte während der Animation bei. Wenn der Knoten nicht definiert ist, sollte das Kanalattribut weggelassen werden.
- Sampler - Definiert Eingabe- und Ausgabepaare: Ein Satz skalarer Gleitkommawerte, die die lineare Zeit in Sekunden darstellen. Alle Werte (Eingabe / Ausgabe) werden im Puffer gespeichert und sind über Accessoren zugänglich. Das Interpolationsattribut speichert den Interpolationswert zwischen Schlüsseln.
Im einfachsten GLTF gibt es keine Animationen. Ein Beispiel stammt aus einer anderen Datei:
"animations": [ { "name": "Animate all properties of one node with different samplers", "channels": [ { "sampler": 0, "target": { "node": 1, "path": "rotation" } }, { "sampler": 1, "target": { "node": 1, "path": "scale" } }, { "sampler": 2, "target": { "node": 1, "path": "translation" } } ], "samplers": [ { "input": 4, "interpolation": "LINEAR", "output": 5 }, { "input": 4, "interpolation": "LINEAR", "output": 6 }, { "input": 4, "interpolation": "LINEAR", "output": 7 } ] },
Haut
Skinning-Informationen, auch Skinning genannt, auch bekannt als Bone-Animation, werden im Skins-Array gespeichert. Jeder Skin wird mithilfe des inverseBindMatrices-Attributs definiert, das sich auf den Accessor mit IBM-Daten (inverse bind matrix) bezieht. Diese Daten werden verwendet, um die Koordinaten auf den gleichen Raum wie jedes Gelenk zu übertragen, sowie das Attribut des Gelenkarrays, in dem die Knotenindizes aufgeführt sind, die als Gelenke für die Hautanimation verwendet werden. Die Reihenfolge der Verbindungen wird im Array skin.joints festgelegt und muss mit der Datenreihenfolge von inverseBindMatrices übereinstimmen. Das Skelettattribut verweist auf ein Knotenobjekt, das die gemeinsame Wurzel der Gelenkhierarchie oder den direkten oder indirekten übergeordneten Knoten einer gemeinsamen Wurzel darstellt.
Ein Beispiel für die Verwendung des Skin-Objekts (nicht im Dreiecksbeispiel):
"skins": [ { "name": "skin_0", "inverseBindMatrices": 0, "joints": [ 1, 2 ], "skeleton": 1 } ]
Die Hauptattribute:
- Name - Hautname
- inverseBindMatrices - Gibt die Zugriffsnummer an, in der Informationen zur Inverse Bind Matrix gespeichert sind
- Gelenke - Gibt die Nummer des Accessors an, auf dem Informationen zu Gelenken gespeichert sind
- Skelett - Gibt die Nummer des Accessors an, der Informationen über die "Wurzel" gespeichert hat.
Gelenk / Gelenk, mit dem das Skelett des Modells beginnt
Kamera
Die Kamera bestimmt die Projektionsmatrix, die durch Transformieren der „Ansicht“ in die Koordinaten des Clips erhalten wird. Wenn es einfacher ist, bestimmen die Kameras das visuelle Erscheinungsbild (Betrachtungswinkel, Blickrichtung usw.), das der Benutzer beim Laden des Modells sieht.
Die Projektion kann "Perspektive" und "Orthogonal" sein. Kameras sind in Knoten enthalten und können Transformationen aufweisen. Kameras sind in Knotenobjekten fixiert und können daher Transformationen aufweisen. Die Kamera ist so definiert, dass die lokale + X-Achse nach rechts gerichtet ist, das Objektiv in Richtung der lokalen -Z-Achse schaut und die Oberseite der Kamera mit der lokalen + Y-Achse ausgerichtet ist. Wenn die Transformation nicht angegeben ist, befindet sich die Kamera am Ursprung. Die Kameras werden im Kamera-Array gespeichert. Jeder von ihnen definiert ein Typattribut, das einen Projektionstyp (Perspektive oder Orthogonal) zuweist, sowie Attribute wie Perspektive oder Orthographie, in denen bereits detailliertere Informationen gespeichert sind. Abhängig vom Vorhandensein des zfar-Attributs können Kameras mit dem Perspektiventyp eine endliche oder unendliche Projektion verwenden.
Eine Beispielkamera in JSON mit Typperspektive. Nicht relevant für ein Beispiel einer minimal korrekten GLTF-Datei (Dreieck):
"cameras": [ { "name": "Infinite perspective camera", "type": "perspective", "perspective": { "aspectRatio": 1.5, "yfov": 0.660593, "znear": 0.01 } } ]
Die Hauptattribute des Kameraobjekts:
- Name - Hautname
- Typ - Kameratyp, Perspektive oder orthografisch.
- Perspektive / Orthographie - Attribut, das Details des entsprechenden Typwerts enthält
- Seitenverhältnis - Seitenverhältnis (fov).
- yfov - vertikaler Sichtfeldwinkel (fov) im Bogenmaß
- zfar - Abstand zur entfernten Schnittebene
- znear - Abstand zur nahen Schnittebene
- Extras - anwendungsspezifische Daten
Minimal gültige GLTF-Datei
Am Anfang des Artikels schrieb ich, dass wir eine minimale GLTF-Datei sammeln werden, die 1 Dreieck enthält. Gepufferter JSON finden Sie unten. Kopieren Sie es einfach in eine Textdatei und ändern Sie das Dateiformat in .gtlf. Um ein 3D-Asset in einer Datei anzuzeigen, können Sie jeden Viewer verwenden, der GLTF unterstützt, aber ich persönlich verwende dies
{ "scenes" : [ { "nodes" : [ 0 ] } ], "nodes" : [ { "mesh" : 0 } ], "meshes" : [ { "primitives" : [ { "attributes" : { "POSITION" : 1 }, "indices" : 0 } ] } ], "buffers" : [ { "uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=", "byteLength" : 44 } ], "bufferViews" : [ { "buffer" : 0, "byteOffset" : 0, "byteLength" : 6, "target" : 34963 }, { "buffer" : 0, "byteOffset" : 8, "byteLength" : 36, "target" : 34962 } ], "accessors" : [ { "bufferView" : 0, "byteOffset" : 0, "componentType" : 5123, "count" : 3, "type" : "SCALAR", "max" : [ 2 ], "min" : [ 0 ] }, { "bufferView" : 1, "byteOffset" : 0, "componentType" : 5126, "count" : 3, "type" : "VEC3", "max" : [ 1.0, 1.0, 0.0 ], "min" : [ 0.0, 0.0, 0.0 ] } ], "asset" : { "version" : "2.0" } }
Was ist das Ergebnis?
Abschließend möchte ich auf die wachsende Beliebtheit von GLTF- und GLB-Formaten hinweisen, die von vielen Unternehmen bereits aktiv genutzt werden und von denen einige bereits aktiv danach streben. Die einfache Nutzung im sozialen Netzwerk Facebook (3D-Posts und in jüngerer Zeit 3D-Fotos), die aktive Nutzung von GLB in Oculus Home sowie eine Reihe von Innovationen, die auf der GDC 2019 angekündigt wurden, tragen wesentlich zur Popularisierung des Formats bei. Leichtigkeit, schnelle Rendergeschwindigkeit, Benutzerfreundlichkeit, Förderung der Khronos-Gruppe und Standardisierung des Formats - dies sind die Hauptvorteile, die, wie ich sicher bin, irgendwann dazu beitragen werden, das Format weiter zu fördern!