{"id":1155,"date":"2017-07-23T17:29:16","date_gmt":"2017-07-23T17:29:16","guid":{"rendered":"http:\/\/demensdeum.com\/blog\/?p=1155"},"modified":"2024-12-16T22:32:46","modified_gmt":"2024-12-16T19:32:46","slug":"opengles-miku","status":"publish","type":"post","link":"https:\/\/demensdeum.com\/blog\/de\/2017\/07\/23\/opengles-miku\/","title":{"rendered":"Es gibt nur Miku"},"content":{"rendered":"<p>Das Ergebnis der Arbeit an der FSGL-Bibliothek mit OpenGL ES und Code:<\/p>\n<p><iframe loading=\"lazy\" src=\"https:\/\/www.youtube.com\/embed\/9L11ezDGRB8\" width=\"560\" height=\"315\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n<p>Als n\u00e4chstes werde ich beschreiben, wie alles programmiert wurde und verschiedene <em>interessante<\/em> Probleme gel\u00f6st wurden.<\/p>\n<p>Zuerst initialisieren wir den OpenGL ES-Kontext, wie ich im vorherigen Beitrag geschrieben habe. Im Folgenden betrachten wir nur das Rendern und eine kurze Beschreibung des Codes.<\/p>\n<h3>Die Matrix beobachtet dich<\/h3>\n<p>Diese Figur von Miku im Video besteht aus Dreiecken. Um in OpenGL ein Dreieck zu zeichnen, m\u00fcssen Sie drei Punkte mit den Koordinaten x, y, z angeben. in 2D-Koordinaten des OpenGL-Kontexts.<br \/>Da wir eine Figur zeichnen m\u00fcssen, die 3D-Koordinaten enth\u00e4lt, m\u00fcssen wir eine <strong>Projektionsmatrix<\/strong> verwenden. Wir m\u00fcssen das Modell auch drehen, vergr\u00f6\u00dfern oder was auch immer wir tun m\u00f6chten &#8211; Hierzu wird die <strong>Modellmatrix<\/strong> verwendet. In OpenGL gibt es kein Konzept einer Kamera; tats\u00e4chlich drehen sich Objekte um eine statische Kamera. Hierzu wird eine <strong>Ansichtsmatrix<\/strong> verwendet.<\/p>\n<p>Um die Implementierung von OpenGL ES zu vereinfachen &#8211; es enth\u00e4lt keine Matrixdaten. Sie k\u00f6nnen Bibliotheken verwenden, die fehlende Funktionalit\u00e4t hinzuf\u00fcgen, zum Beispiel <a href=\"http:\/\/glm.g-truc.net\" target=\"_blank\" rel=\"noopener\">GLM<\/a>.<\/p>\n<h3><strong>Shader<\/strong><\/h3>\n<p>Um es dem Entwickler zu erm\u00f6glichen, alles und in irgendeiner Weise zu zeichnen, muss OpenGL ES Vertex- und Fragment-Shader implementieren. Der Vertex-Shader muss Rendering-Koordinaten als Eingabe erhalten, Transformationen mithilfe von Matrizen durchf\u00fchren und die Koordinaten an gl_Position \u00fcbergeben. Fragment- oder Pixel-Shader &#8211; Zeichnet bereits Farbe\/Textur, wendet \u00dcberlagerung an usw.<\/p>\n<p>Ich habe Shader in GLSL geschrieben. In meiner aktuellen Implementierung sind Shader als <strong>C<\/strong>-Strings<\/p>\n<p> direkt in den Hauptanwendungscode integriert<\/p>\n<h3>Puffer<\/h3>\n<p>Der Vertex-Puffer enth\u00e4lt die Koordinaten der Scheitelpunkte (Vertices); dieser Puffer enth\u00e4lt auch Koordinaten f\u00fcr die Texturierung und andere f\u00fcr Shader notwendige Daten. Nachdem Sie den Vertex-Puffer generiert haben, m\u00fcssen Sie den Zeiger an die Daten f\u00fcr den Vertex-Shader binden. Dies erfolgt mit dem Befehl glVertexAttribPointer, bei dem Sie die Anzahl der Elemente, einen Zeiger auf den Anfang der Daten und die Schrittgr\u00f6\u00dfe angeben m\u00fcssen, die zum Durchlaufen des Puffers verwendet wird. In meiner Implementierung erfolgt die Bindung von Scheitelpunktkoordinaten und Texturkoordinaten f\u00fcr den Pixel-Shader. Es ist jedoch anzumerken, dass die \u00dcbertragung der Daten (Texturkoordinaten) an den Fragment-Shader \u00fcber den Vertex-Shader erfolgt. Um dies zu erreichen, werden die Koordinaten mit <strong>Varying<\/strong> angegeben.<\/p>\n<p>Damit OpenGL wei\u00df, in welcher Reihenfolge Punkte f\u00fcr Dreiecke gezeichnet werden m\u00fcssen &#8211; Sie ben\u00f6tigen einen Indexpuffer (Index). Der Indexpuffer enth\u00e4lt die Scheitelpunktnummer im Array. Unter Verwendung dreier solcher Indizes wird ein Dreieck erhalten.<\/p>\n<h3>Texturen<\/h3>\n<p>Zuerst m\u00fcssen Sie eine Textur f\u00fcr OpenGL laden\/generieren. Hierzu habe ich SDL_LoadBMP verwendet, die Textur wird aus einer BMP-Datei geladen. Es ist jedoch zu beachten, dass nur 24-Bit-BMPs geeignet sind und die Farben darin nicht in der \u00fcblichen RGB-Reihenfolge, sondern in BGR gespeichert werden. Das hei\u00dft, nach dem Laden m\u00fcssen Sie den roten Kanal durch einen blauen ersetzen.<br \/>Texturkoordinaten werden im Format <a href=\"http:\/\/www.opengl-tutorial.org\/beginners-tutorials\/tutorial-5-a-textured-cube\/\" target=\"_blank\" rel=\"noopener\"> angegeben UV< \/a>, das hei\u00dft, Sie m\u00fcssen nur zwei Koordinaten \u00fcbertragen. Die Texturausgabe erfolgt im Fragment-Shader. Dazu m\u00fcssen Sie die Textur in einen Fragment-Shader binden.<\/p>\n<h3>Nichts Besonderes<\/h3>\n<p>Da OpenGL gem\u00e4\u00df unseren Anweisungen 3D bis 2D zeichnet &#8211; dann um die Tiefe zu implementieren und unsichtbare Dreiecke auszuw\u00e4hlen &#8211; Sie m\u00fcssen Culling und einen Tiefenpuffer (Z-Puffer) verwenden. In meiner Implementierung ist es mir gelungen, die manuelle Generierung des Tiefenpuffers mithilfe von zwei Befehlen zu vermeiden: glEnable(GL_DEPTH_TEST); und Auswahlen glEnable(GL_CULL_FACE);<br \/>Stellen Sie au\u00dferdem sicher, dass die Nahebene f\u00fcr die Projektionsmatrix gr\u00f6\u00dfer als Null ist, denn Die \u00dcberpr\u00fcfung der Tiefe mit einer Null-Nahebene funktioniert nicht.<\/p>\n<h3><strong>Rendering<\/strong><\/h3>\n<p>Um den Vertex-Puffer und den Index-Puffer mit etwas Bewusstem zu f\u00fcllen, zum Beispiel dem Miku-Modell, m\u00fcssen Sie dieses Modell laden. Hierf\u00fcr habe ich die Bibliothek <a href=\"https:\/\/github.com\/assimp\/assimp\" target=\"_blank\" rel=\"noopener\">assimp<\/a> verwendet. Miku wurde in eine Wavefront-OBJ-Formatdatei eingef\u00fcgt, mit assimp geladen und die Datenkonvertierung von assimp in Vertex- und Indexpuffer wurde implementiert.<\/p>\n<p>Das Rendern erfolgt in mehreren Schritten:<\/p>\n<ol>\n<li>Rotieren Sie Miku mithilfe der Modellmatrixrotation<\/li>\n<li>Bildschirm und Tiefenpuffer l\u00f6schen<\/li>\n<li>Zeichnen von Dreiecken mit dem glDrawElements-Befehl.<\/li>\n<\/ol>\n<p>N\u00e4chste Stufe &#8211; Implementierung des Renderings in WebGL mit Emscripten.<\/p>\n<p>Quellcode:<br \/><a href=\"https:\/\/github.com\/demensdeum\/OpenGLES3-Experiments\/tree\/master\/8-sdl-gles-obj-textured-assimp-miku\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/demensdeum\/OpenGLES3-Experiments\/tree\/master\/8-sdl-gles-obj-textured-assimp-miku<br \/>\n<\/a>Modell:<br \/><a href=\"https:\/\/sketchfab.com\/models\/7310aaeb8370428e966bdcff414273e7\" target=\"_blank\" rel=\"noopener\">https:\/\/sketchfab.com\/models\/7310aaeb8370428e966bdcff414273e7<\/a><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Das Ergebnis der Arbeit an der FSGL-Bibliothek mit OpenGL ES und Code: Als n\u00e4chstes werde ich beschreiben, wie alles programmiert wurde und verschiedene interessante Probleme gel\u00f6st wurden. Zuerst initialisieren wir den OpenGL ES-Kontext, wie ich im vorherigen Beitrag geschrieben habe. Im Folgenden betrachten wir nur das Rendern und eine kurze Beschreibung des Codes. Die Matrix<a class=\"more-link\" href=\"https:\/\/demensdeum.com\/blog\/de\/2017\/07\/23\/opengles-miku\/\">Continue reading <span class=\"screen-reader-text\">&#8220;Es gibt nur Miku&#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":[76],"class_list":["post-1155","post","type-post","status-publish","format-standard","hentry","category-techie","category-tutorials","tag-opengl","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"de","enabled_languages":["en","ru","zh","de","fr","ja","pt"],"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}}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/posts\/1155","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=1155"}],"version-history":[{"count":26,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/posts\/1155\/revisions"}],"predecessor-version":[{"id":3996,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/posts\/1155\/revisions\/3996"}],"wp:attachment":[{"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/media?parent=1155"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/categories?post=1155"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/tags?post=1155"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}