{"id":2073,"date":"2019-06-23T01:08:42","date_gmt":"2019-06-22T22:08:42","guid":{"rendered":"http:\/\/demensdeum.com\/blog\/?p=2073"},"modified":"2024-12-16T22:32:36","modified_gmt":"2024-12-16T19:32:36","slug":"skeletal-animation-1","status":"publish","type":"post","link":"https:\/\/demensdeum.com\/blog\/de\/2019\/06\/23\/skeletal-animation-1\/","title":{"rendered":"Skelettanimation (Teil 1 \u2013 Shader)"},"content":{"rendered":"<p>In diesem Artikel werde ich mein Verst\u00e4ndnis der Skelettanimation beschreiben, die in allen modernen 3D-Engines zur Animation von Charakteren, Spielumgebungen usw. verwendet wird.<br \/>Ich beginne die Beschreibung mit dem greifbarsten Teil \u2013 &#8211; Vertex-Shader, denn der gesamte Berechnungspfad, egal wie komplex er auch sein mag, endet mit der \u00dcbergabe der vorbereiteten Daten zur Anzeige an den Vertex-Shader.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2080\" src=\"https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2019\/06\/flower-love-friendship-human-body-illustration-skeleton-913687-pxhere.com_.jpg\" alt=\"\" width=\"360\" height=\"228\" \/><\/p>\n<p>Die Skelettanimation geht nach der Verarbeitung auf der CPU in den Vertex-Shader.<br \/>Ich m\u00f6chte Sie an die Formel f\u00fcr Scheitelpunkte ohne Skelettanimation erinnern:<br \/>gl_Position = projectMatrix * viewMatrix * modelMatrix * vertex;<br \/>F\u00fcr diejenigen, die nicht verstehen, wie diese Formel zustande kam, k\u00f6nnen Sie meinen Artikel lesen, der das Prinzip der Arbeit mit Matrizen zur Anzeige von 3D-Inhalten im Kontext von OpenGL beschreibt.<br \/>Im \u00dcbrigen &#8211; Formel zur Implementierung einer Skelettanimation:<br \/>&#8221; vec4animierterVertex = bone0matrix * vertex * bone0weight +&#8221;<br \/>&#8220;bone1matrix * vertex * bone1weight +&#8221;<br \/>&#8220;bone2matrix * vertex * bone2weight +&#8221;<br \/>&#8220;bone3matrix * vertex * bone3weight;\\n&#8221;<br \/>&#8221; gl_Position = projectMatrix * viewMatrix * modelMatrix * animatedVertex;\\n&#8221;<\/p>\n<p>Das hei\u00dft, wir multiplizieren die endg\u00fcltige Knochentransformationsmatrix mit dem Scheitelpunkt und mit dem Gewicht dieser Matrix relativ zum Scheitelpunkt. Jeder Scheitelpunkt kann durch 4 Knochen animiert werden, die St\u00e4rke des Aufpralls wird durch den Knochengewichtsparameter reguliert, die Summe der Aufschl\u00e4ge sollte gleich eins sein.<br \/>Was tun, wenn weniger als 4 Knochen den Scheitelpunkt betreffen? Wir m\u00fcssen das Gewicht zwischen ihnen aufteilen und die Auswirkung des Rests auf Null setzen.<br \/>Mathematisch wird die Multiplikation einer Gewichtung mit einer Matrix \u201eMatrix-Skalar-Multiplikation\u201c genannt. Durch Multiplikation mit einem Skalar k\u00f6nnen Sie die Wirkung der Matrizen auf den resultierenden Scheitelpunkt zusammenfassen.<\/p>\n<p><strong>Die Knochentransformationsmatrizen selbst werden als Array \u00fcbertragen. <\/strong>Dar\u00fcber hinaus enth\u00e4lt das Array Matrizen f\u00fcr das gesamte Modell als Ganzes und nicht f\u00fcr jedes Netz einzeln.<\/p>\n<p>Aber f\u00fcr jeden Scheitelpunkt werden die folgenden Informationen separat \u00fcbertragen:<br \/>&#8211; Index der Matrix, die den Scheitelpunkt beeinflusst<br \/>&#8211; Gewicht der Matrix, das den Scheitelpunkt beeinflusst<br \/>Es wird mehr als ein Knochen \u00fcbertragen, meist wird die Wirkung von 4 Knochen am Scheitelpunkt genutzt.<br \/>Au\u00dferdem muss die Summe der Gewichte der 4 W\u00fcrfel immer gleich eins sein.<br \/>Schauen wir uns als N\u00e4chstes an, wie es im Shader aussieht.<br \/>Matrix-Array:<br \/>&#8220;uniform mat4 bonesMatrices[kMaxBones];&#8221;<\/p>\n<p>Informationen \u00fcber die Wirkung von 4 Knochen auf jedem Scheitelpunkt:<br \/>&#8220;Attribut vec2 bone0info;&#8221;<br \/>&#8220;Attribut vec2 bone1info;&#8221;<br \/>&#8220;Attribut vec2 bone2info;&#8221;<br \/>&#8220;attribute vec2 bone3info;&#8221;<\/p>\n<p>vec2 &#8211; 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\u00fcssen Sie diese Daten in einem zweidimensionalen Vektor \u00fcbertragen? Weil GLSL die \u00dcbergabe von C-lesbaren Strukturen mit g\u00fcltigen Feldern an den Shader nicht unterst\u00fctzt.<\/p>\n<p>Im Folgenden gebe ich ein Beispiel f\u00fcr den Erhalt der notwendigen Informationen aus einem Vektor f\u00fcr die weitere Substitution in die animierteVertex-Formel:<\/p>\n<p>&#8220;int bone0Index = int(bone0info.x);&#8221;<br \/>&#8220;float bone0weight = bone0info.y;&#8221;<br \/>&#8220;mat4 bone0matrix = bonesMatrices[bone0Index];&#8221;<\/p>\n<p>&#8220;int bone1Index = int(bone1info.x);&#8221;<br \/>&#8220;float bone1weight = bone1info.y;&#8221;<br \/>&#8220;mat4 bone1matrix = bonesMatrices[bone1Index];&#8221;<\/p>\n<p>&#8220;int bone2Index = int(bone2info.x);&#8221;<br \/>&#8220;float bone2weight = bone2info.y;&#8221;<br \/>&#8220;mat4 bone2matrix = bonesMatrices[bone2Index];&#8221;<\/p>\n<p>&#8220;int bone3Index = int(bone3info.x);&#8221;<br \/>&#8220;float bone3weight = bone3info.y;&#8221;<br \/>&#8220;mat4 bone3matrix = bonesMatrices[bone3Index];&#8221;<\/p>\n<p>Jetzt sollte die auf der CPU gef\u00fcllte Vertex-Struktur wie folgt aussehen:<br \/>x, y, z, u, v, Bone0index, Bone0weight, Bone1index, Bone1weight, Bone2index, Bone2weight, Bone3index, Bone3weight<\/p>\n<p>Die Vertex-Pufferstruktur wird beim Laden des Modells einmal gef\u00fcllt, aber Transformationsmatrizen werden bei jedem Rendering-Frame von der CPU an den Shader \u00fcbertragen.<\/p>\n<p>In den verbleibenden Teilen beschreibe ich das Prinzip der Animationsberechnung auf der CPU. Bevor ich sie an den Vertex-Shader \u00fcbertrage, beschreibe ich den Baum der Knochenknoten und gehe durch die Hierarchie Animation-Modell-Knoten-Netz, Matrix Interpolation.<\/p>\n<h3>Quellen<\/h3>\n<p><a href=\"http:\/\/ogldev.atspace.co.uk\/www\/tutorial38\/tutorial38.html\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/ogldev.atspace.co. uk\/www\/tutorial38\/tutorial38.html<\/a><\/p>\n<h3>Quellcode<\/h3>\n<p><a href=\"https:\/\/gitlab.com\/demensdeum\/skeletal-animation\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gitlab.com\/demensdeum\/skeletal-animation<\/a <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In diesem Artikel werde ich mein Verst\u00e4ndnis 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 \u2013 &#8211; Vertex-Shader, denn der gesamte Berechnungspfad, egal wie komplex er auch sein mag, endet mit der \u00dcbergabe der vorbereiteten Daten zur Anzeige an den<a class=\"more-link\" href=\"https:\/\/demensdeum.com\/blog\/de\/2019\/06\/23\/skeletal-animation-1\/\">Continue reading <span class=\"screen-reader-text\">&#8220;Skelettanimation (Teil 1 \u2013 Shader)&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[61,52],"tags":[108],"class_list":["post-2073","post","type-post","status-publish","format-standard","hentry","category-techie","category-tutorials","tag-skeletal-animation","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"de","enabled_languages":["en","ru","zh","de","fr","ja","pt","hi"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"ru":{"title":true,"content":true,"excerpt":false},"zh":{"title":true,"content":true,"excerpt":false},"de":{"title":true,"content":true,"excerpt":false},"fr":{"title":true,"content":true,"excerpt":false},"ja":{"title":true,"content":true,"excerpt":false},"pt":{"title":true,"content":true,"excerpt":false},"hi":{"title":false,"content":false,"excerpt":false}}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/posts\/2073","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/comments?post=2073"}],"version-history":[{"count":13,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/posts\/2073\/revisions"}],"predecessor-version":[{"id":3953,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/posts\/2073\/revisions\/3953"}],"wp:attachment":[{"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/media?parent=2073"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/categories?post=2073"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/tags?post=2073"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}