Skelettanimation (Teil 1 – Shader)

In diesem Artikel werde ich mein Verständnis der Skelettanimation beschreiben, die in allen modernen 3D-Engines zur Animation von Charakteren, Spielumgebungen usw. verwendet wird.
Ich beginne die Beschreibung mit dem greifbarsten Teil – – Vertex-Shader, denn der gesamte Berechnungspfad, egal wie komplex er auch sein mag, endet mit der Übergabe der vorbereiteten Daten zur Anzeige an den Vertex-Shader.

Die Skelettanimation geht nach der Verarbeitung auf der CPU in den Vertex-Shader.
Ich möchte Sie an die Formel für Scheitelpunkte ohne Skelettanimation erinnern:
gl_Position = projectMatrix * viewMatrix * modelMatrix * vertex;
Für diejenigen, die nicht verstehen, wie diese Formel zustande kam, können Sie meinen Artikel lesen, der das Prinzip der Arbeit mit Matrizen zur Anzeige von 3D-Inhalten im Kontext von OpenGL beschreibt.
Im Übrigen – Formel zur Implementierung einer Skelettanimation:
” vec4animierterVertex = bone0matrix * vertex * bone0weight +”
“bone1matrix * vertex * bone1weight +”
“bone2matrix * vertex * bone2weight +”
“bone3matrix * vertex * bone3weight;\n”
” gl_Position = projectMatrix * viewMatrix * modelMatrix * animatedVertex;\n”

Das heißt, wir multiplizieren die endgültige Knochentransformationsmatrix mit dem Scheitelpunkt und mit dem Gewicht dieser Matrix relativ zum Scheitelpunkt. Jeder Scheitelpunkt kann durch 4 Knochen animiert werden, die Stärke des Aufpralls wird durch den Knochengewichtsparameter reguliert, die Summe der Aufschläge sollte gleich eins sein.
Was tun, wenn weniger als 4 Knochen den Scheitelpunkt betreffen? Wir müssen das Gewicht zwischen ihnen aufteilen und die Auswirkung des Rests auf Null setzen.
Mathematisch wird die Multiplikation einer Gewichtung mit einer Matrix „Matrix-Skalar-Multiplikation“ genannt. Durch Multiplikation mit einem Skalar können Sie die Wirkung der Matrizen auf den resultierenden Scheitelpunkt zusammenfassen.

Die Knochentransformationsmatrizen selbst werden als Array übertragen. Darüber hinaus enthält das Array Matrizen für das gesamte Modell als Ganzes und nicht für jedes Netz einzeln.

Aber für jeden Scheitelpunkt werden die folgenden Informationen separat übertragen:
– Index der Matrix, die den Scheitelpunkt beeinflusst
– Gewicht der Matrix, das den Scheitelpunkt beeinflusst
Es wird mehr als ein Knochen übertragen, meist wird die Wirkung von 4 Knochen am Scheitelpunkt genutzt.
Außerdem muss die Summe der Gewichte der 4 Würfel immer gleich eins sein.
Schauen wir uns als Nächstes an, wie es im Shader aussieht.
Matrix-Array:
“uniform mat4 bonesMatrices[kMaxBones];”

Informationen über die Wirkung von 4 Knochen auf jedem Scheitelpunkt:
“Attribut vec2 bone0info;”
“Attribut vec2 bone1info;”
“Attribut vec2 bone2info;”
“attribute vec2 bone3info;”

vec2 – In der X-Koordinate speichern wir den Index des Knochens (und konvertieren ihn im Shader in int), in der Y-Koordinate speichern wir das Gewicht des Aufpralls des Knochens auf den Scheitelpunkt. Warum müssen Sie diese Daten in einem zweidimensionalen Vektor übertragen? Weil GLSL die Übergabe von C-lesbaren Strukturen mit gültigen Feldern an den Shader nicht unterstützt.

Im Folgenden gebe ich ein Beispiel für den Erhalt der notwendigen Informationen aus einem Vektor für die weitere Substitution in die animierteVertex-Formel:

“int bone0Index = int(bone0info.x);”
“float bone0weight = bone0info.y;”
“mat4 bone0matrix = bonesMatrices[bone0Index];”

“int bone1Index = int(bone1info.x);”
“float bone1weight = bone1info.y;”
“mat4 bone1matrix = bonesMatrices[bone1Index];”

“int bone2Index = int(bone2info.x);”
“float bone2weight = bone2info.y;”
“mat4 bone2matrix = bonesMatrices[bone2Index];”

“int bone3Index = int(bone3info.x);”
“float bone3weight = bone3info.y;”
“mat4 bone3matrix = bonesMatrices[bone3Index];”

Jetzt sollte die auf der CPU gefüllte Vertex-Struktur wie folgt aussehen:
x, y, z, u, v, Bone0index, Bone0weight, Bone1index, Bone1weight, Bone2index, Bone2weight, Bone3index, Bone3weight

Die Vertex-Pufferstruktur wird beim Laden des Modells einmal gefüllt, aber Transformationsmatrizen werden bei jedem Rendering-Frame von der CPU an den Shader übertragen.

In den verbleibenden Teilen beschreibe ich das Prinzip der Animationsberechnung auf der CPU. Bevor ich sie an den Vertex-Shader übertrage, beschreibe ich den Baum der Knochenknoten und gehe durch die Hierarchie Animation-Modell-Knoten-Netz, Matrix Interpolation.

Quellen

http://ogldev.atspace.co. uk/www/tutorial38/tutorial38.html

Quellcode

https://gitlab.com/demensdeum/skeletal-animation

Leave a Comment

Your email address will not be published. Required fields are marked *