diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:15 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:15 -0500 |
commit | 4b1a9203c547c019fc5398082ae19a3f3d4c3efe (patch) | |
tree | d4a40e13ceeb9f85479605110a76e7a4d5f3b56b /files/de/web/api/webgl_api | |
parent | 33058f2b292b3a581333bdfb21b8f671898c5060 (diff) | |
download | translated-content-4b1a9203c547c019fc5398082ae19a3f3d4c3efe.tar.gz translated-content-4b1a9203c547c019fc5398082ae19a3f3d4c3efe.tar.bz2 translated-content-4b1a9203c547c019fc5398082ae19a3f3d4c3efe.zip |
initial commit
Diffstat (limited to 'files/de/web/api/webgl_api')
10 files changed, 1370 insertions, 0 deletions
diff --git a/files/de/web/api/webgl_api/index.html b/files/de/web/api/webgl_api/index.html new file mode 100644 index 0000000000..cd699e7ee1 --- /dev/null +++ b/files/de/web/api/webgl_api/index.html @@ -0,0 +1,258 @@ +--- +title: WebGL +slug: Web/API/WebGL_API +tags: + - WebGL + - WebGL2 +translation_of: Web/API/WebGL_API +--- +<div>{{WebGLSidebar}}</div> + +<div class="summary"> +<p>WebGL (Web Graphics Library) ist eine Javascript-API zum Rendern interaktiver 3D und 2D Grafiken mittels eines kompatiblen Web-Browsers ohne Einsatz zusätzlicher Plugins. Mit <a class="external" href="http://www.khronos.org/webgl/" title="http://www.khronos.org/webgl/">WebGL</a> steht eine API zur Verfügung, die an <a class="external" href="http://www.khronos.org/opengles/" title="http://www.khronos.org/opengles/">OpenGL ES 2.0</a> angelehnt ist und deren Inhalte mittels eines {{HTMLElement("canvas")}} Elements dargestellt werden.</p> +</div> + +<p>WebGL steht ab <a href="/en-US/Firefox" title="Firefox 4 for developers">Firefox</a> 4+, <a href="http://www.google.com/chrome/" title="http://www.google.com/chrome/">Google Chrome</a> 9+, <a href="http://www.opera.com/" title="http://www.opera.com/">Opera</a> 12+, <a href="http://www.apple.com/safari/" title="http://www.apple.com/fr/safari/">Safari </a>5.1+ und <a href="http://windows.microsoft.com/en-us/internet-explorer/browser-ie" title="http://windows.microsoft.com/en-us/internet-explorer/download-ie">Internet Explorer</a> 11+ zur Verfügung. Allerdings muss auch die Hardware des Zielgerätes dieses Feature unterstützen.</p> + +<p>WebGL2 steht ab <a href="/en-US/Firefox" title="Firefox 4 for developers">Firefox</a> 51+, <a href="http://www.google.com/chrome/" title="http://www.google.com/chrome/">Google Chrome</a> 56+ und <a href="http://www.opera.com/" title="http://www.opera.com/">Opera</a> 42+ standardmäßig zur Verfügung. WebGL2 wird derzeit nicht von Internet Explorer oder Edge unterstützt.</p> + +<p>Das {{HTMLElement("canvas")}} Element kann auch von <a href="/de/docs/Web/API/Canvas_API">Canvas 2D</a> genutzt werden, um 2D Grafiken rendern zu können.</p> + +<h2 id="Reference">Reference</h2> + +<div class="index"> +<ul> + <li>{{domxref("WebGLRenderingContext")}}</li> + <li>{{domxref("WebGL2RenderingContext")}} {{experimental_inline}}</li> + <li>{{domxref("WebGLActiveInfo")}}</li> + <li>{{domxref("WebGLBuffer")}}</li> + <li>{{domxref("WebGLContextEvent")}}</li> + <li>{{domxref("WebGLFramebuffer")}}</li> + <li>{{domxref("WebGLProgram")}}</li> + <li>{{domxref("WebGLQuery")}} {{experimental_inline}}</li> + <li>{{domxref("WebGLRenderbuffer")}}</li> + <li>{{domxref("WebGLSampler")}} {{experimental_inline}}</li> + <li>{{domxref("WebGLShader")}}</li> + <li>{{domxref("WebGLShaderPrecisionFormat")}}</li> + <li>{{domxref("WebGLSync")}} {{experimental_inline}}</li> + <li>{{domxref("WebGLTexture")}}</li> + <li>{{domxref("WebGLTransformFeedback")}} {{experimental_inline}}</li> + <li>{{domxref("WebGLUniformLocation")}}</li> + <li>{{domxref("WebGLVertexArrayObject")}} {{experimental_inline}}</li> +</ul> +</div> + +<h3 id="Extensions">Extensions</h3> + +<div class="index"> +<ul> + <li>{{domxref("ANGLE_instanced_arrays")}}</li> + <li>{{domxref("EXT_blend_minmax")}}</li> + <li>{{domxref("EXT_color_buffer_float")}}</li> + <li>{{domxref("EXT_color_buffer_half_float")}}</li> + <li>{{domxref("EXT_disjoint_timer_query")}}</li> + <li>{{domxref("EXT_frag_depth")}}</li> + <li>{{domxref("EXT_sRGB")}}</li> + <li>{{domxref("EXT_shader_texture_lod")}}</li> + <li>{{domxref("EXT_texture_filter_anisotropic")}}</li> + <li>{{domxref("OES_element_index_uint")}}</li> + <li>{{domxref("OES_standard_derivatives")}}</li> + <li>{{domxref("OES_texture_float")}}</li> + <li>{{domxref("OES_texture_float_linear")}}</li> + <li>{{domxref("OES_texture_half_float")}}</li> + <li>{{domxref("OES_texture_half_float_linear")}}</li> + <li>{{domxref("OES_vertex_array_object")}}</li> + <li>{{domxref("WEBGL_color_buffer_float")}}</li> + <li>{{domxref("WEBGL_compressed_texture_atc")}}</li> + <li>{{domxref("WEBGL_compressed_texture_etc")}}</li> + <li>{{domxref("WEBGL_compressed_texture_etc1")}}</li> + <li>{{domxref("WEBGL_compressed_texture_pvrtc")}}</li> + <li>{{domxref("WEBGL_compressed_texture_s3tc")}}</li> + <li>{{domxref("WEBGL_debug_renderer_info")}}</li> + <li>{{domxref("WEBGL_debug_shaders")}}</li> + <li>{{domxref("WEBGL_depth_texture")}}</li> + <li>{{domxref("WEBGL_draw_buffers")}}</li> + <li>{{domxref("WEBGL_lose_context")}}</li> +</ul> +</div> + +<h3 id="Events">Events</h3> + +<ul> + <li><a href="/de/docs/Web/Events/webglcontextlost">webglcontextlost</a></li> + <li><a href="/de/docs/Web/Events/webglcontextrestored">webglcontextrestored</a></li> + <li><a href="/de/docs/Web/Events/webglcontextcreationerror">webglcontextcreationerror</a></li> +</ul> + +<h3 id="Konstanten_und_Typen">Konstanten und Typen</h3> + +<ul> + <li><a href="/de/docs/Web/API/WebGL_API/Constants">WebGL Konstanten</a></li> + <li><a href="/de/docs/Web/API/WebGL_API/Types">WebGL Typen</a></li> +</ul> + +<h2 id="Themen">Themen</h2> + +<p>Die folgenden acht Artikel bauen aufeinander auf.</p> + +<dl> + <dt><a href="/de/WebGL/Einführung_in_WebGL" title="de/WebGL/Einführung in WebGL">Einführung in WebGL</a></dt> + <dd>Wie man einen WebGL-Kontext herstellt.</dd> + <dt><a href="/de/WebGL/Hinzufügen_von_2D_Inhalten_in_einen_WebGL-Kontext" title="de/WebGL/Hinzufügen von 2D Inhalten in einen WebGL-Kontext">Hinzufügen von 2D Inhalten in einen WebGL-Kontext</a></dt> + <dd>Wie eine einfache, flache Form mittels WebGL erstellt wird.</dd> + <dt><a href="/de/WebGL/Farben_mittels_Shader_in_einen_WebGL-Kontext_hinzufügen" title="en/WebGL/Farben mittels Shader in einen WebGL-Kontext hinzufügen">Farben mittels Shader in einen WebGL-Kontext hinzufügen</a></dt> + <dd>Zeigt wie Farben mit Shadern auf die Form gebracht werden können.</dd> + <dt><a href="/de/WebGL/Objekte_mit_WebGL_animieren" title="de/WebGL/Objekte mit WebGL animieren">Objekte mit WebGL animieren</a></dt> + <dd>Erklärt wie Objekte rotiert und verschiebt werden, um eine einfache Animation zu erstellen.</dd> + <dt><a href="/de/WebGL/3D-Objekte_mit_WebGL_erstellen" title="de/WebGL/3D-Objekte_mit_WebGL_erstellen">3D-Objekte mit WebGL erstellen</a></dt> + <dd>Erläutert wie dreidimensionale Objekte erstellt und animiert werden (ein Würfel dient als Beispiel).</dd> + <dt><a href="/de/WebGL/Texturen_in_WebGL_verwenden" title="de/WebGL/Texturen in WebGL verwenden">Texturen in WebGL verwenden</a></dt> + <dd>Demonstriert wie Texturen auf die Oberfläche eines Objektes gezeichnet werden können.</dd> + <dt><a href="/de/WebGL/Beleuchtung_in_WebGL" title="de/WebGL/Beleuchtung in WebGL">Beleuchtung in WebGL</a></dt> + <dd>Wie Beleuchtungseffekte in unserem WebGL-Kontext simuliert werden.</dd> + <dt><a href="/de/WebGL/Animierte_Texturen_in_WebGL" title="de/WebGL/Animierte Texturen in WebGL">Animierte Texturen in WebGL</a></dt> + <dd>Animierte Texturen werden mittels einem Ogg-Video auf der Oberfläche eines rotierenden Würfels realisiert.</dd> +</dl> + +<h2 id="Ressourcen">Ressourcen</h2> + +<dl> + <dt><a class="link-https" href="https://www.khronos.org/registry/webgl/specs/1.0/" title="https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/doc/spec/WebGL-spec.html">WebGL Spezifikation</a></dt> + <dd>Der Entwurf der WebGL Spezifikation.</dd> + <dt><a class="external" href="http://www.khronos.org/webgl/" title="http://www.khronos.org/webgl/">Khronos WebGL Seite</a></dt> + <dd>Die Hauptseite für WebGL der Khronos Group.</dd> + <dt><a class="external" href="http://learningwebgl.com/blog/" title="http://learningwebgl.com/blog/">Learning WebGL</a></dt> + <dd>Eine Reihe von Tutorials über WebGL (Englisch).</dd> + <dt><a class="external" href="http://learningwebgl.com/cookbook/index.php/" title="http://learningwebgl.com/cookbook/index.php/">Das WebGL Kochbuch</a></dt> + <dd>Rezepte für das Schreiben von WebGL-Code (Englisch).</dd> + <dt><a class="external" href="http://sylvester.jcoglan.com/" title="http://sylvester.jcoglan.com/">Sylvester</a></dt> + <dd>Eine Open-Source Bibliothek, die das Verarbeiten von Vektoren und Matrizen erleichtert.</dd> + <dt><a class="external" href="http://planet-webgl.org/" title="http://planet-webgl.org/">Planet WebGL</a></dt> + <dd>Eine Feed-Sammlung von Leuten, die in der WebGL Community aktiv sind.</dd> +</dl> + +<h2 id="Spezifikationen">Spezifikationen</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Spezifikation</th> + <th scope="col">Status</th> + <th scope="col">Hinweis</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('WebGL')}}</td> + <td>{{Spec2('WebGL')}}</td> + <td>Grundlegende Definition. Basierend auf OpenGL ES 2.0</td> + </tr> + <tr> + <td>{{SpecName('WebGL2')}}</td> + <td>{{Spec2('WebGL2')}}</td> + <td>Erweiterung von WebGL1. Basierend auf OpenGL ES 3.0.</td> + </tr> + <tr> + <td>{{SpecName('OpenGL ES 2.0')}}</td> + <td>{{Spec2('OpenGL ES 2.0')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('OpenGL ES 3.0')}}</td> + <td>{{Spec2('OpenGL ES 3.0')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="Browser-Kompatibilität">Browser-Kompatibilität</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Edge</th> + <th>Firefox (Gecko)</th> + <th>Chrome</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatGeckoDesktop("2.0")}}</td> + <td>9</td> + <td>11</td> + <td>12<sup>[1]</sup></td> + <td>5.1<sup>[1]</sup></td> + </tr> + <tr> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Edge</th> + <th>Firefox Mobile (Gecko)</th> + <th>Chrome for Android</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>4</td> + <td>25<sup>[1]</sup></td> + <td>{{CompatNo}}</td> + <td>12<sup>[1]</sup></td> + <td>8.1</td> + </tr> + </tbody> +</table> +</div> + +<p>[1] Die Implementierung dieses Features ist experimentell.</p> + +<h3 id="Kompatibilitätshinweise">Kompatibilitätshinweise</h3> + +<p>Neben dem Browser muss auch die GPU selbst dieses Feature unterstützen. So ist zum Beispiel S3 Texture Compression (S3TC) derzeit nur auf Desktop-Rechnern und Tegra-basierenden Tablets verfügbar. Die meisten Browser stellen den {{domxref("HTMLCanvasElement.getContext", "WebGL-Context")}} durch den <code>webgl</code> Contextnamen zur Verfügung - ältere Browser benötigen hingegen manchmal stattdessen den Contextnamen <code>experimental-webgl</code>.</p> + +<p>Das kommende <a href="/de/docs/Web/API/WebGL2RenderingContext">WebGL 2</a> ist vollständig abwärtskompatibel und wird über den Contextnamen <code>experimental-webgl2</code> aufgerufen. Ab Firefox 42.0 ist der Aufruf auch über den Contextnamen <code>webgl2</code> möglich - WebGL2 ist bis einschließlich Firefox 50 ein experimentelles Feature und kann zu Testzwecken über <a href="#WebGL2_enabling">Flag-Settings</a> des <a href="https://support.mozilla.org/de/kb/konfigurationseditor-fur-firefox" title="Der Konfigurationseditor von Firefox (about:config) listet Programmeinstellungen aus den Dateien prefs.js und user.js des Firefox-Profilordners sowie die Standardeinstellungen auf. Viele dieser erweiterten Optionen sind in den normalen Einstellungen nicht verfügbar.">Konfigurationseditors</a> aktiviert werden. WebGL2 ist ab Firefox 51+, Chrome 56+ und Opera 42+ standardmäßig aktiviert - Internet Explorer und Edge bieten derzeit noch keinen Support für WebGL2.</p> + +<h3 id="Anmerkungen_zu_Gecko">Anmerkungen zu Gecko</h3> + +<h4 id="WebGL_Debugging_und_Testing">WebGL Debugging und Testing</h4> + +<p>Ab Gecko 10.0 {{geckoRelease("10.0")}} werden zwei Möglichkeiten geboten, die WebGL-Fähigkeit des Browsers zu Testzwecken zu beeinflussen:</p> + +<dl> + <dt><code>webgl.min_capability_mode</code></dt> + <dd>Ein boolescher Wert, der bei <code>true</code> einen minimalen Kompatibiätsmodus zur Verfügung stellt. Ist dieser Modus aktiviert, wird WebGL ausschließlich mit dem geringsten Features betrieben, die von der WebGL-Spezifikation definiert wurden. Damit lässt sich sicherstellen, dass dein WebGL-Code auf jedem Gerät unabhängig besonderer Fähigkeiten lauffähig ist. Der Standarardwert ist <code>false</code>.</dd> + <dt><code>webgl.disable_extensions</code></dt> + <dd>Ein boolescher Wert, der bei <code>true</code> alle WebGL Extensions deaktiviert. Der Standarardwert ist <code>false</code>.</dd> +</dl> + +<h4 id="WebGL2_Aktivierung">WebGL2 Aktivierung</h4> + +<dl> + <dt><code>webgl.enable-prototype-webgl2</code> (ab Firefox 38)</dt> + <dt><code>webgl.enable-webgl2</code> (ab Firefox 50)</dt> + <dd>Ein boolescher Wert, der bei <code>true</code> den bisher experimentellen WebGL2-Context im Browser aktiviert. Der Standarardwert ist <code>false</code> - ab Firefox 51 ist der Standardwert <code>true</code>.</dd> +</dl> + +<h2 id="Siehe_auch">Siehe auch</h2> + +<ul> + <li><a href="/de/docs/Web/API/Canvas_API">Canvas</a></li> + <li><a href="https://developer.mozilla.org/de/docs/Web/API/WebGLRenderingContext/getSupportedExtensions#Browser_compatibility">Kompatibilitäts-Hinweise zu WebGL Extensions</a></li> +</ul> diff --git a/files/de/web/api/webgl_api/tutorial/3d-objekte_mit_webgl_erstellen/index.html b/files/de/web/api/webgl_api/tutorial/3d-objekte_mit_webgl_erstellen/index.html new file mode 100644 index 0000000000..d3a21591fd --- /dev/null +++ b/files/de/web/api/webgl_api/tutorial/3d-objekte_mit_webgl_erstellen/index.html @@ -0,0 +1,126 @@ +--- +title: 3D-Objekte mit WebGL erstellen +slug: Web/API/WebGL_API/Tutorial/3D-Objekte_mit_WebGL_erstellen +tags: + - Tutorial + - WebGL +translation_of: Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL +--- +<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Objekte_mit_WebGL_animieren", "Web/API/WebGL_API/Tutorial/Texturen_in_WebGL_verwenden")}}</p> + +<p>Bringen wir unser Quadrat in die dritte Dimension, indem wir fünf oder mehr Flächen hinzufügen und daraus einen Würfel machen. Um das effizient zu machen, wechseln wir vom Zeichnen direkt über die Vertices zur <code>gl.drawArray()</code> Methode, um den Vertex-Array als eine Tabelle zu verwenden und die einzelnen Vertices in dieser Tabelle als Referenz für Positionen jeder Fläche zu definieren, indem wir <code>gl.drawElements()</code> aufrufen.</p> + +<p>Bedenken Sie: Jede Fläche benötigt vier Vertices, die diese definieren, aber jeder Vertex wird von drei Flächen verwendet. Wir können eine Menge Daten sparen, indem wir eine Liste aller 24 Vertices erstellen und uns dann auf jeden Vertex durch dessen Index in der Liste beziehen, anstatt den gesamten Koordinatensatz zu verwenden.</p> + +<h2 id="Die_Vertex-Positionen_des_Würfels_definieren">Die Vertex-Positionen des Würfels definieren</h2> + +<p>Zunächst wollen wir den Positionsspeicher der Vertices erstellen, indem wir den Code in <code>initBuffers()</code> ändern. Das geschieht genau so wie für das Quadrat, allerdings haben wir hier ein paar Datensätze mehr, da wir 24 Vertices (4 pro Seite) haben müssen:</p> + +<pre class="brush: js"> var vertices = [ + // vordere Fläche + -1.0, -1.0, 1.0, + 1.0, -1.0, 1.0, + 1.0, 1.0, 1.0, + -1.0, 1.0, 1.0, + + // hintere Fläche + -1.0, -1.0, -1.0, + -1.0, 1.0, -1.0, + 1.0, 1.0, -1.0, + 1.0, -1.0, -1.0, + + // obere Fläche + -1.0, 1.0, -1.0, + -1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, -1.0, + + // untere Fläche + -1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + 1.0, -1.0, 1.0, + -1.0, -1.0, 1.0, + + // rechte Fläche + 1.0, -1.0, -1.0, + 1.0, 1.0, -1.0, + 1.0, 1.0, 1.0, + 1.0, -1.0, 1.0, + + // linke Fläche + -1.0, -1.0, -1.0, + -1.0, -1.0, 1.0, + -1.0, 1.0, 1.0, + -1.0, 1.0, -1.0 + ]; +</pre> + +<h2 id="Die_Farben_der_Vertices_definieren">Die Farben der Vertices definieren</h2> + +<p>Außerdem müssen wir einen Array für die Farben der 24 Vertices erstellen. Dieser Code definiert zunächst die Farben für jede Fläche und verwendet dann eine Schleife, um jeden der Vertices mit einer Farbe zu bestücken.</p> + +<pre class="brush: js"> var colors = [ + [1.0, 1.0, 1.0, 1.0], // vordere Fläche: weiß + [1.0, 0.0, 0.0, 1.0], // hintere Fläche: rot + [0.0, 1.0, 0.0, 1.0], // obere Fläche: grün + [0.0, 0.0, 1.0, 1.0], // untere Fläche: blau + [1.0, 1.0, 0.0, 1.0], // rechte Fläche: gelb + [1.0, 0.0, 1.0, 1.0] // linke Fläche: violett + ]; + + var generatedColors = []; + + for (j=0; j<6; j++) { + var c = colors[j]; + + for (var i=0; i<4; i++) { + generatedColors = generatedColors.concat(c); + } + } + + cubeVerticesColorBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesColorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(generatedColors), gl.STATIC_DRAW); +</pre> + +<h2 id="Das_Element-Array_definieren">Das Element-Array definieren</h2> + +<p>Sobald die Vertex-Arrays generiert worden sind, müssen wir das Element-Array erstellen.</p> + +<pre class="brush: js"> cubeVerticesIndexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer); + + // Dieser Array definiert jede Fläche als zwei Dreiecke über die Indizes + // im Vertex-Array, um die Position jedes Dreiecks festzulegen. + + var cubeVertexIndices = [ + 0, 1, 2, 0, 2, 3, // vorne + 4, 5, 6, 4, 6, 7, // hinten + 8, 9, 10, 8, 10, 11, // oben + 12, 13, 14, 12, 14, 15, // unten + 16, 17, 18, 16, 18, 19, // rechts + 20, 21, 22, 20, 22, 23 // links + ] + + // Sende nun das Element-Array zum GL + + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, + new WebGLUnsignedShortArray(cubeVertexIndices), gl.STATIC_DRAW); +</pre> + +<p>Das <code>cubeVertexIndices</code> Array definiert jede Fläche als ein paar von Dreiecken, alle Vertices des Dreiecks werden als ein Index im Vertex-Array des Würfels festgelegt. Daher ist der Würfel aus einer Sammlung von 12 Dreiecken beschrieben.</p> + +<h2 id="Den_Würfel_zeichnen">Den Würfel zeichnen</h2> + +<p>Als nächstes müssen wir etwas Code zur <code>drawScene()</code> Funktion hinzufügen, um über den Indexspeicher des Würfels zu zeichnen. Wir fügen neue <code>bindBuffer()</code> und <code>drawElements()</code> Aufrufe hinzu:</p> + +<pre class="brush: js"> gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer); + setMatrixUniforms(); + gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0); +</pre> + +<p>Da jede Seite unseres Würfels aus zwei Dreiecken besteht, gibt es 6 Vertices pro Seite, oder 36 Vertices im Würfel, obwohl einige davon doppelt sind. Da unser Index-Array jedoch aus einfachen Integern besteht, stellt dies keinen unkoordinierbaren Betrag an Daten dar, welcher für jeden Frame der Animation durchgegangen werden muss.</p> + +<p>Jetzt haben wir einen animierten Würfel, welcher herum springt, rotiert und über sechs unterschiedliche Seiten verfügt. Wenn Ihr Browser WebGL unterstützt, <a href="/samples/webgl/sample5/index.html" title="https://developer.mozilla.org/samples/webgl/sample5/index.html">schauen Sie sich hier die Demo in Aktion an</a>.</p> + +<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Objekte_mit_WebGL_animieren", "Web/API/WebGL_API/Tutorial/Texturen_in_WebGL_verwenden")}}</p> diff --git a/files/de/web/api/webgl_api/tutorial/animierte_texturen_in_webgl/index.html b/files/de/web/api/webgl_api/tutorial/animierte_texturen_in_webgl/index.html new file mode 100644 index 0000000000..bfeb362b8e --- /dev/null +++ b/files/de/web/api/webgl_api/tutorial/animierte_texturen_in_webgl/index.html @@ -0,0 +1,89 @@ +--- +title: Animierte Texturen in WebGL +slug: Web/API/WebGL_API/Tutorial/Animierte_Texturen_in_WebGL +tags: + - Tutorial + - WebGL +translation_of: Web/API/WebGL_API/Tutorial/Animating_textures_in_WebGL +--- +<p>{{WebGLSidebar("Tutorial") }} {{Previous("Web/API/WebGL_API/Tutorial/Beleuchtung_in_WebGL")}}</p> + +<p>In dieser Demo bauen wir auf das vorherige Beispiel auf, indem wir die statischen Texturen mit den Frames eines OGG-Video ersetzen. Das ist nicht sehr schwer zu schreiben, sieht aber umso besser aus. Fangen wir an.</p> + +<h2 id="Zugang_zum_Video">Zugang zum Video</h2> + +<p>Zunächst müssen wir etwas HTML hinzufügen, um das <a href="/de/HTML/Element/video"><code>video</code></a> Element zu erstellen, welches wir verwenden, um die Video-Frames zu erhalten:</p> + +<pre class="brush: js"><video id="video" src="Firefox.ogv" autobuffer='true'"> + Ihr Browser scheint das HTML5 <code>&lt;video&gt;</code> Element nicht zu unterstützen. +</video> +</pre> + +<p>Das erstellt einfach ein Element, um die Video-Datei "Firefox.ogv" abzuspielen. Wir benutzen CSS, um zu verhindern, dass das Video angezeigt wird:</p> + +<pre class="brush: css">video { + display: none; +} +</pre> + +<p>Dann schenken wir dem JavaScript Code wieder unsere Aufmerksamkeit und fügen eine neue Zeile zur <code>start()</code> Funktion hinzu, um einen Bezug zum Video-Element herzustellen:</p> + +<pre class="brush: js">videoElement = document.getElementById("video"); +</pre> + +<p>Und wir ersetzen den Code, der die Intervall-gesteuerten Aufrufe von <code>drawScene()</code> setzt, mit diesem Code:</p> + +<pre class="brush: js">videoElement.addEventListener("canplaythrough", startVideo, true); +videoElement.addEventListener("ended", videoDone, true); +</pre> + +<p>Die Idee ist hier, dass wir die Animation nicht starten wollen, bevor das Video nicht ausreichend zwischengespeichert wurde, sodass es dann ohne Unterbrechung abgespielt werden kann. Wir fügen also einen Event-Listener hinzu, um auf das <code>video</code> Element zu warten bis es uns mitteilt, dass genug zwischengespeichert wurde und das komplette Video ohne Pause abgespielt werden kann. Wir fügen außerdem einen zweiten Event-Listener hinzu, sodass wir die Animation stoppen können, wenn das Video beendet ist und wir so nicht unnötig den Prozessor belasten.</p> + +<p>Die <code>startVideo()</code> Funktion sieht so aus:</p> + +<pre class="brush: js">function startVideo() { + videoElement.play(); + videoElement.addEventListener("timeupdate", updateTexture, true); + setInterval(drawScene, 15); +} +</pre> + +<p>Hier wird einfach das Video gestartet und ein Event-Handler bereitgestellt, der aufgerufen wird, wenn ein neuer Frame des Videos verfügbar ist. Dann werden die Intervall-gesteuerten Aufrufe der <code>drawScene()</code> Funktion eingerichtet, um den Würfel zu rendern.</p> + +<p>Die <code>videoDone()</code> Funktion ruft einfach {{ domxref("window.clearInterval") }} auf, um die Intervallaufrufe zu beenden, die die Animation aktualisieren.</p> + +<h2 id="Die_Video-Frames_als_Textur_verwenden">Die Video-Frames als Textur verwenden</h2> + +<p>Die nächste Änderung erhält die <code>initTexture()</code> Funktion, welche viel einfacher wird, weil kein Bild mehr geladen werden muss. Stattdessen muss nun das Textur-Mapping aktiviert werden und ein leeres Textur-Objekt zum späteren Gebrauch erstellt werden:</p> + +<pre class="brush: js">function initTextures() { + gl.enable(gl.TEXTURE_2D); + cubeTexture = gl.createTexture(); +} +</pre> + +<p>So sieht die <code>updateTexture()</code> Funktion aus. Hier wird wirklich Arbeit verrichtet:</p> + +<pre class="brush: js">function updateTexture() { + gl.bindTexture(gl.TEXTURE_2D, cubeTexture); + gl.texImage2D(gl.TEXTURE_2D, 0, videoElement, true); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); + gl.generateMipmap(gl.TEXTURE_2D); + gl.bindTexture(gl.TEXTURE_2D, null); +} +</pre> + +<p>Sie kennen diesen Code bereits. Es ist fast identisch zur <code>handleTextureLoaded()</code> Routine im vorherigen Beispiel, mit der Ausnahme, dass wir <code>texImage2D()</code> nicht mit einem <code>Image</code> Objekt sondern mit dem <code>video</code> Element aufrufen.</p> + +<p><code>updateTexture()</code> wird jedes Mal aufgerufen, wenn sich das <code>timeupdate</code> Event vom <code>video</code> Element meldet. Dieses Event wird gesendet, wenn sich die Zeit des aktuellen Frames ändert, sodass wir wissen, dass wir unsere Textur nur dann aktualisieren müssen, wenn neue Daten verfügbar sind.</p> + +<p>Das war alles! Wenn Sie eine Browser mit Unterstützung von WebGL verwenden, können Sie sich <a href="/samples/webgl/sample8/index.html" title="https://developer.mozilla.org/samples/webgl/sample8/index.html">das Beispiel in Aktion ansehen</a>.</p> + +<h2 id="Siehe_auch">Siehe auch</h2> + +<ul> + <li><a href="/de/Audio_und_Video_in_Firefox">Audio und Video in Firefox</a></li> +</ul> + +<p>{{Previous("Web/API/WebGL_API/Tutorial/Beleuchtung_in_WebGL")}}</p> diff --git a/files/de/web/api/webgl_api/tutorial/beleuchtung_in_webgl/index.html b/files/de/web/api/webgl_api/tutorial/beleuchtung_in_webgl/index.html new file mode 100644 index 0000000000..bd65b5bb40 --- /dev/null +++ b/files/de/web/api/webgl_api/tutorial/beleuchtung_in_webgl/index.html @@ -0,0 +1,172 @@ +--- +title: Beleuchtung in WebGL +slug: Web/API/WebGL_API/Tutorial/Beleuchtung_in_WebGL +tags: + - Tutorial + - WebGL +translation_of: Web/API/WebGL_API/Tutorial/Lighting_in_WebGL +--- +<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Texturen_in_WebGL_verwenden", "Web/API/WebGL_API/Tutorial/Animierte_Texturen_in_WebGL")}}</p> + +<p>Als Erstes sollten wir verstehen, dass WebGL nicht wie OpenGL über eine eigene Unterstützung für die Beleuchtung verfügt. Das müssen wir selbst machen. Glücklicherweise ist es nicht sehr schwer und dieser Artikel versucht Ihnen die Grundlagen dazu näher zu bringen.</p> + +<h2 id="Beleuchtung_und_Schattierung_simulieren">Beleuchtung und Schattierung simulieren</h2> + +<p>Obwohl wir nicht weiter ins Detail über die Theorie hinter simulierter Beleuchtung in 3D Grafiken gehen wollen, was außerdem weit über diesen Artikel hinaus gehen würde, ist es gut zu wissen wie es ungefähr funktioniert. Anstatt hier nun in aller Tiefe zu diskutieren, sollten Sie einen Blick auf den <a class="external" href="http://de.wikipedia.org/wiki/Phong_Shading">»Phong Shading« Artikel</a> auf Wikipedia werfen, welcher einen guten Überblick über das meist genutzte Beleuchtungsmodell liefert.</p> + +<p>Es gibt drei grundlegende Typen zur Beleuchtung:</p> + +<p><strong>Umgebungslicht</strong> ist das Licht, das die Szene umgibt. Es weist in keine Richtung und bestrahlt jede Oberfläche in gleicher Weise, egal in welche Richtung es zeigt.</p> + +<p><strong>Gerichtetes Licht</strong> ist das Licht, das von einer festgelegten Richtung ausgestrahlt wird. Dieses Licht ist so weit weg, sodass sich jeder Photon parallel zu jedem anderen Photon bewegt. Sonnenlicht ist zum Beispiel gerichtetes (direktionales) Licht.</p> + +<p><strong>Punktbeleuchtung</strong> ist das Licht, das von einem Punkt ausgestrahlt wird und von dort radial in alle Richtungen verläuft. So funktionieren zum Beispiel die Glühbirnen im Alltag.</p> + +<p>Für unsere Zwecke vereinfachen wir das Beleuchtungsmodell, indem wir nur gerichtetes Licht und Umgebungslicht betrachten. Wir haben hier keine Highlights, die wir mit Punktbeleuchtung oder Glanzlicht in dieser Szene hervorheben wollen. Stattdessen werden wir Umgebungslicht mit einem einzelnen, gerichteten Licht verwenden, welches auf den rotierenden Würfel aus der <a href="/de/WebGL/Texturen_in_WebGL_verwenden">vorherigen Demo</a> zeigt.</p> + +<p>Wenn Sie die Konzepte der Punktbeleuchtung und des Glanzlichtes hinter sich gelassen haben, gibt es dennoch zwei kleine Informationen, die Sie benötigen werden, wenn wir unser gerichtetes Licht implementieren:</p> + +<ol> + <li>Wir müssen die <strong>Oberflächennormale</strong> mit jedem Vertex verbinden. Das ist ein Vektor, der senkrecht zur Oberfläche des Vertex ist.</li> + <li>Wir müssen die Richtung in welche das Licht strahlt wissen. Diese wird durch den <strong>Richtungsvektor</strong> angegeben.</li> +</ol> + +<p>Dann aktualisieren wir den Vertex-Shader, um die Farbe jedes Vertices, unter Berücksichtigung des Umgebungslichts und dem Effekt des gerichteten Lichts (sowie dessen Winkel mit dem es auf die Oberfläche trifft), einzustellen. Wir werden sehen, wie genau wir das machen, wenn wir einen Blick auf den Code für den Shader werfen.</p> + +<h2 id="Die_Normalen_für_die_Vertices_erstellen">Die Normalen für die Vertices erstellen</h2> + +<p>Als Erstes müssen wir einen Array für die Normalen für alle Vertices erstellen, die unseren Würfel umfassen. Da ein Würfel ein sehr einfaches Objekt ist, ist dies auch sehr einfach zu erstellen. Für komplexere Objekte wird das Berechnen der Normalen schon umfassender.</p> + +<pre class="brush: js"> cubeVerticesNormalBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesNormalBuffer); + + var vertexNormals = [ + // vorne + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + + // hinten + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + + // oben + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + + // unten + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + + // rechts + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + + // links + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0 + ]; + + gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(vertexNormals), gl.STATIC_DRAW); +</pre> + +<p>Das sollte Ihnen schon bekannt vorkommen: Wir erstellen einen neuen Buffer, verknüpfen den Array damit und senden dann unseren Vertex-Normalen-Array in den Buffer, indem wir <code>bufferData()</code> aufrufen.</p> + +<p>Dann fügen wir Code zu <code>drawScene()</code> hinzu, um das Normalen-Array mit einem Shader-Attribut zu verknüpfen, sodass der Shader-Code darauf zugreifen kann:</p> + +<pre class="brush: js"> gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesNormalBuffer); + gl.vertexAttribPointer(vertexNormalAttribute, 3, gl.FLOAT, false, 0, 0); +</pre> + +<p>Schließlich müssen wir den Code aktualisieren, welcher die Einheitsmatrizen erstellt, um eine <strong>Normalenmatrix</strong> zu generieren und zum Shader auszuliefern. Diese wird verwendet, um die Normalen umzuwandeln, wenn die aktuelle Orientierung des Würfels in Beziehung zur Lichtquelle behandelt wird:</p> + +<pre class="brush: js"> var normalMatrix = mvMatrix.inverse(); + normalMatrix = normalMatrix.transpose(); + var nUniform = gl.getUniformLocation(shaderProgram, "uNormalMatrix"); + gl.uniformMatrix4fv(nUniform, false, new WebGLFloatArray(normalMatrix.flatten())); +</pre> + +<h2 id="Die_Shader_aktualisieren">Die Shader aktualisieren</h2> + +<p>Jetzt sind alle Daten, die von den Shadern gebraucht werden, verfügbar. Wir müssen nun den Code in den Shadern selbst aktualisieren.</p> + +<h3 id="Der_Vertex-Shader">Der Vertex-Shader</h3> + +<p>Zunächst aktualisieren wir den Vertex-Shader, sodass dieser einen Schattenwert für jeden Vertex auf Basis des Umgebungslichts sowie des direktionalen Lichts berechnet. Werfen wir einen Blick auf den Code:</p> + +<pre class="brush: html"> <script id="shader-vs" type="x-shader/x-vertex"> + attribute vec3 aVertexNormal; + attribute vec3 aVertexPosition; + attribute vec2 aTextureCoord; + + uniform mat4 uNormalMatrix; + uniform mat4 uMVMatrix; + uniform mat4 uPMatrix; + + varying vec2 vTextureCoord; + varying vec3 vLighting; + + void main(void) { + gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); + vTextureCoord = aTextureCoord; + + // Beleuchtungseffekt anwenden + + vec3 ambientLight = vec3(0.6, 0.6, 0.6); + vec3 directionalLightColor = vec3(0.5, 0.5, 0.75); + vec3 directionalVector = vec3(0.85, 0.8, 0.75); + + vec4 transformedNormal = uNormalMatrix * vec4(aVertexNormal, 1.0); + + float directional = max(dot(transformedNormal.xyz, directionalVector), 0.0); + vLighting = ambientLight + (directionalLightColor * directional); + } + </script> +</pre> + +<p>Sobald die Position des Vertex berechnet wurde und wir die Koordinaten des Texels (welcher passend zum Vertex ist) erhalten haben, können wir den Schatten für den Vertex berechnen.</p> + +<p>Als Erstes wandeln wir die Normale auf Basis der aktuellen Position und Orientierung des Würfels um, indem wir die Normale des Vertexes mit der Normalenmatrix multiplizieren. Dann können wir den Betrag an direktionalem Licht, welcher auf den Vertex angewendet werden soll, berechnen, indem wir das Skalarprodukt der umgewandelten Normalen und des direktionalen Vektors (Richtung aus der das Licht kommt) bilden. Wenn dieser Wert kleiner als Null ist, setzen wir den Wert auf Null fest, da man nicht weniger als Null Licht haben kann.</p> + +<p>Wenn der Betrag des direktionalen Lichts berechnet wurde, können wir den Beleuchtungswert generieren, indem wir das Umgebungslicht nehmen und das Produkt der Farbe des direktionalen Lichts und den Betrag an direktionalem Licht bereitstellen. Als Ergebnis haben wir nun einen RGB-Wert, welcher vom Fragment-Shader verwendet wird, um die Farbe jedes Pixels den wir rendern einzustellen.</p> + +<h3 id="Der_Fragment-Shader">Der Fragment-Shader</h3> + +<p>Der Fragment-Shader muss nun aktualisiert werden, um den berechneten Beleuchtungswert vom Vertex-Shader zu berücksichtigen:</p> + +<pre class="brush: js"> <script id="shader-fs" type="x-shader/x-fragment"> + varying vec2 vTextureCoord; + varying vec3 vLighting; + + uniform sampler2D uSampler; + + void main(void) { + vec4 texelColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); + + gl_FragColor = vec4(texelColor.rgb * vLighting, texelColor.a); + } + </script> +</pre> + +<p>Hier erhalten wir nun die Farbe des Texels, genau so wie wir es im vorherigen Beispiel getan haben. Bevor wir die Farbe der Fragmente aber festlegen, multiplizieren wir die Texel-Farbe mit dem Beleuchtungswert, um die Texel-Farbe so einzustellen, dass diese den Effekt der Lichtquelle berücksichtigt.</p> + +<p>Und das war's! Wenn Sie einen Browser verwenden, der WebGL unterstützt, können Sie <a href="/samples/webgl/sample7/index.html" title="https://developer.mozilla.org/samples/webgl/sample7/index.html">einen Blick auf die Live-Demo werfen</a>.</p> + +<h2 id="Übungen_für_den_Leser">Übungen für den Leser</h2> + +<p>Dies ist natürlich ein sehr einfaches Beispiel, welches eine Beleuchtung pro Vertex implementiert. Für fortgeschrittene Grafiken, möchten Sie sicher eine Beleuchtung pro Pixel implementieren, aber dies wird Sie in die Richtung leiten.</p> + +<p>Sie können nun also versuchen mit der Richtung der Lichtquelle zu experimentieren, die Farbe der Leuchtquelle zu ändern und so weiter.</p> + +<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Texturen_in_WebGL_verwenden", "Web/API/WebGL_API/Tutorial/Animierte_Texturen_in_WebGL")}}</p> diff --git a/files/de/web/api/webgl_api/tutorial/einführung_in_webgl/index.html b/files/de/web/api/webgl_api/tutorial/einführung_in_webgl/index.html new file mode 100644 index 0000000000..5906f95761 --- /dev/null +++ b/files/de/web/api/webgl_api/tutorial/einführung_in_webgl/index.html @@ -0,0 +1,73 @@ +--- +title: Einführung in WebGL +slug: Web/API/WebGL_API/Tutorial/Einführung_in_WebGL +tags: + - Tutorial + - WebGL +translation_of: Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL +--- +<p>{{WebGLSidebar("Tutorial")}} {{Next("Web/API/WebGL_API/Tutorial/Hinzufügen_von_2D_Inhalten_in_einen_WebGL-Kontext")}}</p> + +<p>Mit <a class="external" href="http://www.khronos.org/webgl/" title="http://www.khronos.org/webgl/">WebGL</a> steht eine API zur Verfügung, die auf <a class="external" href="http://www.khronos.org/opengles/" title="http://www.khronos.org/opengles/">OpenGL ES 2.0</a> basiert, um 3D Rendering im HTML <a href="/de/HTML/Element/canvas" title="de/HTML/canvas"><code>canvas</code></a> Element zu ermöglichen. WebGL Programme bestehen aus Steuercode in JavaScript und Shadercode (GLSL), der auf dem Grafikprozessor (GPU) des Computers ausgeführt wird. WebGL Elemente können mit anderen HTML Elementen kombiniert werden.</p> + +<p>Dieser Artikel ist eine Einführung in die Grundlagen von WebGL. Es wird vorausgesetzt, dass einige mathematischen Kenntnisse im 3D-Bereich (Matrizen) vorhanden sind. Dieser Artikel wird daher keine 3D-Grafik-Konzepte vermitteln. Es gibt einen anfängergeeigneten Leitfaden mit Programmieraufgaben in unserem Lernbereich: <a href="https://developer.mozilla.org/en-US/docs/Learn/WebGL">Learn WebGL for 2D and 3D graphics</a>.</p> + +<p>DIe hier verwendeten Codebeispiele finden sich auch im <a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial">webgl-examples GitHub repository</a>.</p> + +<h2 id="3D_Rendering_vorbereiten">3D Rendering vorbereiten</h2> + +<p>Um WebGL benutzen zu können, wird als erstes ein <code>canvas</code> Element benötigt. Der folgende HTML-Code definiert eine <code>canvas</code> Zeichenfläche.</p> + +<pre class="brush: html"><body> + <canvas id="glCanvas" width="640" height="480"></canvas> +</body> +</pre> + +<h3 id="Vorbereitung_des_WebGL-Kontexts">Vorbereitung des WebGL-Kontexts</h3> + +<p>Die <code>main()</code> Funktion im JavaScript Code wird aufgerufen, nachdem das Dokument geladen wurde. Die Aufgabe der Funktion ist, den WebGL-Kontext festzulegen und mit dem Rendering zu beginnen.</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="function token">main</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + +<span class="keyword token">function</span> <span class="function token">main</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="keyword token">const</span> canvas <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">querySelector</span><span class="punctuation token">(</span><span class="string token">"#glCanvas"</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="comment token">// Initialisierung des GL Kontexts</span> + <span class="keyword token">const</span> gl <span class="operator token">=</span> canvas<span class="punctuation token">.</span><span class="function token">getContext</span><span class="punctuation token">(</span><span class="string token">"webgl"</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + + <span class="comment token">// Nur fortfahren, wenn WebGL verfügbar ist und funktioniert</span> + <span class="keyword token">if</span> <span class="punctuation token">(</span><span class="operator token">!</span>gl<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="function token">alert</span><span class="punctuation token">(</span><span class="string token">"Unable to initialize WebGL. Your browser or machine may not support it."</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="keyword token">return</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span> + + <span class="comment token">// Setze clear color auf schwarz, vollständig sichtbar</span> + gl<span class="punctuation token">.</span><span class="function token">clearColor</span><span class="punctuation token">(</span><span class="number token">0.0</span><span class="punctuation token">,</span> <span class="number token">0.0</span><span class="punctuation token">,</span> <span class="number token">0.0</span><span class="punctuation token">,</span> <span class="number token">1.0</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="comment token">// Lösche den color buffer mit definierter clear color</span> + gl<span class="punctuation token">.</span><span class="function token">clear</span><span class="punctuation token">(</span>gl<span class="punctuation token">.</span>COLOR_BUFFER_BIT<span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span></code></pre> + +<p>Als erstes verschaffen wir uns eine Referenz zum <code>canvas</code> Element und speichern sie in der <code>canvas</code> Variable.</p> + +<p>Sobald wir den Bezug zum canvas haben, versuchen wir einen zugehörigen <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext">WebGLRenderingContext</a> zu erhalten, indem wir <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext">getContext</a> aufrufen und dabei den String <code>"webgl"</code> mitgeben. Falls der Browser WebGL nicht unterstützt, wird <code>getContext null</code> zurückgeben, woraufhin wir den Nutzer benachrichtigen und das Script verlassen.</p> + +<p>Wenn der Kontext erfolgreich initialisiert wurde, ist <code>gl</code> eine Variable für den Kontext. In diesem Fall setzen wir die clear color auf schwarz, und löschen den zugehörigen Kontext (der canvas wird mit der Hintergrundfarbe neu gezeichnet)</p> + +<p>An dieser Stelle ist genug Code vorhanden, um den WebGL-Kontext erfolgreich zu initialisieren. Ein großer, leerer, schwarzer Kasten sollte zu sehen sein, der darauf wartet mit weiteren Inhalten gefüttert zu werden.</p> + +<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample1/index.html', 670, 510) }}</p> + +<p><a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample1">Vollständigen Code ansehen</a> | <a href="http://mdn.github.io/webgl-examples/tutorial/sample1/">Demo in neuer Seite öffnen</a></p> + +<h2 id="Siehe_auch">Siehe auch</h2> + +<p> </p> + +<ul> + <li><a href="https://dev.opera.com/articles/introduction-to-webgl-part-1/">An introduction to WebGL</a>: Verfasst von Luz Caballero, veröffentlicht auf dev.opera.com. Der Artikel behandelt, was WebGL ist, erklärt wie es funktioniert (einschließlich Render Warteschlange) und stellt einige WebGL Bibliotheken vor. </li> + <li><a href="http://webglfundamentals.org/">WebGL Fundamentals</a>: WebGL Grundlagen </li> + <li><a href="http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Table-of-Contents.html">An intro to modern OpenGL:</a> Eine Reihe netter Artikel über OpenGL, verfasst von Joe Groff, die eine verständliche Einführung in OpenGL bieten, von der Geschichte bis zum wichtigen Aspekt der Grafik Pipeline. Außerdem enthält es Beispiele, die demonstrieren, wie OpenGL funktioniert. Wer lernen will, was OpenGL eigentlich ist, findet hier einen guten Ausgangspunkt.</li> +</ul> + +<p> </p> + +<p>{{Next("Web/API/WebGL_API/Tutorial/Hinzufügen_von_2D_Inhalten_in_einen_WebGL-Kontext")}}</p> diff --git a/files/de/web/api/webgl_api/tutorial/farben_mittels_shader_in_einen_webgl-kontext_hinzufügen/index.html b/files/de/web/api/webgl_api/tutorial/farben_mittels_shader_in_einen_webgl-kontext_hinzufügen/index.html new file mode 100644 index 0000000000..94068822d5 --- /dev/null +++ b/files/de/web/api/webgl_api/tutorial/farben_mittels_shader_in_einen_webgl-kontext_hinzufügen/index.html @@ -0,0 +1,97 @@ +--- +title: Farben mittels Shader in einen WebGL-Kontext hinzufügen +slug: >- + Web/API/WebGL_API/Tutorial/Farben_mittels_Shader_in_einen_WebGL-Kontext_hinzufügen +tags: + - Tutorial + - WebGL +translation_of: Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL +--- +<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Hinzufügen_von_2D_Inhalten_in_einen_WebGL-Kontext", "Web/API/WebGL_API/Tutorial/Objekte_mit_WebGL_animieren")}}</p> + +<p>Wir haben ein simples Quadrat <a href="/de/WebGL/Hinzufügen_von_2D_Inhalten_in_einen_WebGL-Kontext" title="de/WebGL/Hinzufügen_von_2D_Inhalten_in_einen_WebGL-Kontext">im vorherigen Teil</a> erstellt, im nächsten Schritt wollen wir ein bisschen Farbe ins Spiel bringen. Dafür sind Änderungen an den Shadern erforderlich.</p> + +<h2 id="Farben_zu_den_Eckpunkten_hinzufügen">Farben zu den Eckpunkten hinzufügen</h2> + +<p>In der Computergrafik werden Objekte mit einer Reihe von Punkten erstellt. Jeder Punkt hat eine Position und eine Farbe. Standardmäßig werden alle anderen Pixelfarben (und alle weiteren Attribute, darunter die Position) über eine lineare Interpolation berechnet, die automatisch glatte Verläufe erstellt. Vorher hat unser Vertex-Shader keine festgelegten Farben auf die Punkte (Vertices) angewendet und der Fragment-Shader legte die feste Farbe weiß für jeden Pixel fest, sodass das gesamte Quadrat komplett weiß gezeichnet wurde.</p> + +<p>Nun wollen wir in jeder Ecke des Quadrats einen Verlauf in einer unterschiedlichen Farbe rendern: rot, blau, grün und weiß. Als erstes sollten wir daher diese Farben in den vier Eckpunkten einrichten. Um das zu machen, müssen wir zunächst einen Array der Vertex-Farben erstellen und diesen dann in einen WebGL Buffer speichern. Das erreichen wir durch die folgenden Zeilen in unserer <code>initBuffers()</code> Funktion:</p> + +<pre class="brush: js">var colors = [ + 1.0, 1.0, 1.0, 1.0, // weiß + 1.0, 0.0, 0.0, 1.0, // rot + 0.0, 1.0, 0.0, 1.0, // grün + 0.0, 0.0, 1.0, 1.0 // blau +]; + +squareVerticesColorBuffer = gl.createBuffer(); +gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer); +gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); +} +</pre> + +<p>Dieser Code definiert zuerst einen JavaScript Array, welcher die vier Farb-Vektoren mit jeweils vier Werten für die jeweilige Farbe enthält. Dann wird ein neuer WebGL Buffer angewiesen diese Farben zu speichern und der Array wird in WebGL Floats konvertiert und im Buffer gespeichert.</p> + +<p>Um die Farben schließlich zu verwenden, muss der der Vertex-Shader aktualisiert werden, um die entsprechende Farbe vom Farb-Buffer zu erhalten:</p> + +<pre class="brush: html"><script id="shader-vs" type="x-shader/x-vertex"> + attribute vec3 aVertexPosition; + attribute vec4 aVertexColor; + + uniform mat4 uMVMatrix; + uniform mat4 uPMatrix; + + varying vec4 vColor; + + void main(void) { + gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); + vColor = aVertexColor; + } +</script> +</pre> + +<p>Der wichtigste Unterschied ist hier, dass wir für jeden Punkt (Vertex) die Farbe entsprechend des Farb-Arrays setzen.</p> + +<h2 id="Die_Fragmente_mit_Farben_versehen">Die Fragmente mit Farben versehen</h2> + +<p>Als Erinnerung, so sah unser Fragment-Shader vorher aus:</p> + +<pre class="brush: html"><script id="shader-fs" type="x-shader/x-fragment"> + void main(void) { + gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); + } +</script> +</pre> + +<p>Um nun die interpolierte Farbe für jeden Pixel aufzugreifen, müssen wir dies einfach so ändern, dass wir den Wert der <code>vColor</code> Variable erhalten:</p> + +<pre><script id="shader-fs" type="x-shader/x-fragment"> + varying vec4 vColor; + + void main(void) { + gl_FragColor = vColor; + } +</script> +</pre> + +<p>Das ist eine sehr einfache Änderung. Anstatt des festen Wertes vorher, erhält jedes Fragment jetzt einfach die interpolierte Farbe, basierend auf der Position relativ zu den Kontenpunkten (Vertices).</p> + +<h2 id="Mit_den_Farben_zeichnen">Mit den Farben zeichnen</h2> + +<p>Als nächstes ist es nötig, Code zur <code>initShaders()</code> Routine hinzuzufügen, um das Farbattribut für das Shader-Programm zu initialisieren:</p> + +<pre class="brush: js"> vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor"); + gl.enableVertexAttribArray(vertexColorAttribute); +</pre> + +<p>Dann wird <code>drawScene()</code> abgeändert, um schließlich die Farben zu verwenden, wenn das Quadrat gezeichnet wird:</p> + +<pre class="brush: js"> gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer); + gl.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0); +</pre> + +<p>Jetzt sollten Sie <a href="/samples/webgl/sample3/index.html" title="https://developer.mozilla.org/samples/webgl/sample3/index.html">das Beispiel in einem WebGL kompatiblen Browser</a> sehen und Ihre Ausgabe sollte so wie im Bild unten gezeichnet werden (das Quadrat ist innerhalb eines schwarzen Felds zu sehen):</p> + +<p><img alt="screenshot.png" class="default internal" src="/@api/deki/files/4081/=screenshot.png"></p> + +<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Hinzufügen_von_2D_Inhalten_in_einen_WebGL-Kontext", "Web/API/WebGL_API/Tutorial/Objekte_mit_WebGL_animieren")}}</p> diff --git a/files/de/web/api/webgl_api/tutorial/hinzufügen_von_2d_inhalten_in_einen_webgl-kontext/index.html b/files/de/web/api/webgl_api/tutorial/hinzufügen_von_2d_inhalten_in_einen_webgl-kontext/index.html new file mode 100644 index 0000000000..56c267f394 --- /dev/null +++ b/files/de/web/api/webgl_api/tutorial/hinzufügen_von_2d_inhalten_in_einen_webgl-kontext/index.html @@ -0,0 +1,238 @@ +--- +title: Hinzufügen von 2D Inhalten in einen WebGL-Kontext +slug: Web/API/WebGL_API/Tutorial/Hinzufügen_von_2D_Inhalten_in_einen_WebGL-Kontext +tags: + - WebGL +translation_of: Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context +--- +<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Einführung_in_WebGL", "Web/API/WebGL_API/Tutorial/Farben_mittels_Shader_in_einen_WebGL-Kontext_hinzufügen")}}</p> + +<p>Sobald der <a href="/de/WebGL/Einführung_in_WebGL" title="de/WebGL/Einführung in WebGL">WebGL-Kontext</a> erfolgreich erstellt wurde, können wir anfangen darin zu rendern. Am einfachsten beginnen wir mit einem einfachen, zweidimensionalen, untextuierten Objekt. Fangen wir also damit an, ein Stück Code zu schreiben, um ein Quadrat zu zeichnen.</p> + +<h3 id="Hinweis_zur_deutschen_Übersetzung_dieses_Abschnitts">Hinweis zur deutschen Übersetzung dieses Abschnitts</h3> + +<p>Die deutsche Übersetzung bezieht sich auf ältere Version des Beispielcodes als der englische Originaltext. Der im deutschen Text beschriebene Code hat einige Probleme:</p> + +<ul> + <li>Er ist unvollständig (die makePerspective() Funktion fehlt).</li> + <li>Er verwendet globale Variablen die in der einen Funktion gesetzt, in der anderen wieder gelesen werden. Dies gilt als schlechte Programmierpraxis.</li> + <li>Die Shader werden aus dem HTML DOM geladen, anstatt als Strings in JavaScript erzeugt. Diese Design-Entscheidung wird nicht begründet.</li> +</ul> + +<p>Um das Beispiel selber nachzuprogrammieren ist es daher empfehlenswert, <a href="/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context">auf die englische Version des Tutorials</a> zu wechseln. Vielleicht haben Sie ja auch Lust, <a href="/de/docs/Web/API/WebGL_API/Tutorial/Hinzuf%C3%BCgen_von_2D_Inhalten_in_einen_WebGL-Kontext$edit">diese Version ins Deutsche zu übersetzen</a>?</p> + +<h2 id="Beleuchtung_der_Szene">Beleuchtung der Szene</h2> + +<p>Das Wichtigste, das wir verstehen müssen bevor wir anfangen können, ist, dass wir, uns bereits in einer dreidimensionalen Umgebung befinden, obwohl wir nur ein zweidimensionales Objekt in diesem Beispiel rendern wollen. Das heißt, wir müssen jetzt bereits Shader einsetzen, die unsere einfache Szene beleuchten und solche erstellen, die unser Objekt zeichnen. Diese Shader werden festlegen wie unser Quadrat später beleuchtet sein wird.</p> + +<h3 id="Initialisierung_der_Shader">Initialisierung der Shader</h3> + +<p>Shader sind durch die <a class="external" href="http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf" title="http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf">OpenGL ES Shading Language (pdf)</a> spezifiziert. Damit es einfacher ist unsere Inhalte zu warten und zu aktualisieren, können wir unseren Code so schreiben, dass die Shader im HTML Dokument gefunden werden, anstatt alles mittels JavaScript zu bauen. Werfen wir einen Blick auf unsere <code>initShaders()</code> Routine, welche diese Aufgabe übernimmt:</p> + +<pre class="brush: js">function initShaders() { + var fragmentShader = getShader(gl, "shader-fs"); + var vertexShader = getShader(gl, "shader-vs"); + + // Erzeuge Shader + + shaderProgram = gl.createProgram(); + gl.attachShader(shaderProgram, vertexShader); + gl.attachShader(shaderProgram, fragmentShader); + gl.linkProgram(shaderProgram); + + // Wenn die das Aufrufen der Shader fehlschlägt, + // gib eine Fehlermeldung aus: + + if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { + alert("Initialisierung des Shaderprogramms nicht möglich."); + } + + gl.useProgram(shaderProgram); + + vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); + gl.enableVertexAttribArray(vertexPositionAttribute); +} + +</pre> + +<p>Es werden zwei Shader in dieser Routine geladen; der Erste, der <code>fragmentShader</code>, wird vom <a href="/de/HTML/Element/Script" title="de/HTML/Element/Script"><code>script</code></a> Element mit der Id "shader-fs" geladen. Der Zweite, der <code>vertexShader</code>, wird vom <a href="/de/HTML/Element/Script" title="de/HTML/Element/Script"><code>script</code></a> Element mit der Id "shader-vs" geladen. Wir werden im nächsten Abschnitt noch näher auf die <code>getShader()</code> Funktion eingehen. Diese Routine holt sich dann die Shader aus dem DOM.</p> + +<p>In diesem Teil erstellen wir noch das Shaderprogramm, in dem wir die Funktion <code>createProgram()</code> aufrufen, die beiden Shader anhängen und das Shaderprogramm verlinken. Danach wird der Zustand des <code>LINK_STATUS</code> Parameters überprüft, um sicher zu gehen, dass das Programm erfolgreich verlinkt wurde. Wenn das der Fall ist, aktivieren wir das neue Shaderprogramm.</p> + +<h3 id="Shader_aus_dem_DOM_laden">Shader aus dem DOM laden</h3> + +<p>Die <code>getShader()</code> Routine ruft ein Shaderprogramm mit dem festgelegtem Namen aus dem DOM auf, gibt das kompilierte Shaderprogramm zurück oder ist leer, wenn nichts geladen oder kompiliert worden konnte.</p> + +<pre class="brush: js">function getShader(gl, id) { + var shaderScript = document.getElementById(id); + + if (!shaderScript) { + return null; + } + + var theSource = ""; + var currentChild = shaderScript.firstChild; + + while(currentChild) { + if (currentChild.nodeType == 3) { + theSource += currentChild.textContent; + } + + currentChild = currentChild.nextSibling; + }</pre> + +<p>Wenn das Element mit der festgelegten Id gefunden wurde, wird der Text in die Variable <code>theSource</code> gespeichert.</p> + +<pre class="brush: js"> var shader; + + if (shaderScript.type == "x-shader/x-fragment") { + shader = gl.createShader(gl.FRAGMENT_SHADER); + } else if (shaderScript.type == "x-shader/x-vertex") { + shader = gl.createShader(gl.VERTEX_SHADER); + } else { + return null; // Unbekannter Shadertyp + }</pre> + +<p>Jetzt wo der Code für die Shader gelesen wurde, können wir uns die MIME Typen der Shader angucken, um festzulegen, ob es ein Vertex-Shader (MIME Typ: "x-shader/x-vertex") oder ein Fragment-Shader (MIME Typ: "x-shader/x-fragment") ist. Danach werden dann die entsprechenden Shadertypen erstellt.</p> + +<pre class="brush: js"> gl.shaderSource(shader, theSource); + + // Kompiliere das Shaderprogramm + + gl.compileShader(shader); + + // Überprüfe, ob die Kompilierung erfolgreich war + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + alert("Es ist ein Fehler beim Kompilieren der Shader aufgetaucht: " + gl.getShaderInfoLog(shader)); + return null; + } + + return shader; +} +</pre> + +<p>Schließlich wird der Shader kompiliert. Falls ein Fehler während der Kompilierung auftritt, zeigen wir die Fehlermeldung an und geben null zurück. Andernfalls wird der kompilierte Shader zurückgegeben.</p> + +<h3 id="Die_Shader">Die Shader</h3> + +<p>Nun müssen wir die eigentlichen Shaderprogramme in unser HTML schreiben. Wie genau diese Shader arbeiten, übersteigt das Ziel dieses Tutorials, wir gehen daher nur auf das Wesentliche ein.</p> + +<h4 id="Fragment-Shader">Fragment-Shader</h4> + +<p>Jeder Pixel in einem Vieleck wird <strong>Fragment</strong> in der GL-Fachsprache genannt. Die Aufgabe des Fragment-Shaders ist es, die Farbe für jeden Pixel bereitzustellen. In unserem Fall ordnen wir einfach jedem Pixel eine weiße Farbe zu.</p> + +<p><code>gl_FragColor</code> ist eine eingebaute GL Variable, die für die Farbe des Fragments verwendet wird.</p> + +<pre class="brush: html"><script id="shader-fs" type="x-shader/x-fragment"> + + void main(void) { + gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); + } +</script> +</pre> + +<h4 id="Vertex-Shader">Vertex-Shader</h4> + +<p>Der Vertex-Shader definiert die Position und Form von jedem Punkt.</p> + +<pre class="brush: html"><script id="shader-vs" type="x-shader/x-vertex"> + attribute vec3 aVertexPosition; + + uniform mat4 uMVMatrix; + uniform mat4 uPMatrix; + + + void main(void) { + gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); + } +</script> +</pre> + +<h2 id="Das_Objekt_erstellen">Das Objekt erstellen</h2> + +<p>Bevor wir unser Quadrat rendern können, müssen wir einen Puffer erstellen, der unsere Punkte enthält. Das werden wir mittels einer Funktion machen, die wir <code>initBuffers()</code> nennen. Wenn wir zu mehr fortgeschrittenen WebGL-Konzepten kommen, wird diese Routine vergrößert, um mehr - und komplexere - 3D-Objekte zu erstellen.</p> + +<pre class="brush: js">var horizAspect = 480.0/640.0; + +function initBuffers() { + squareVerticesBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer); + + var vertices = [ + 1.0, 1.0, 0.0, + -1.0, 1.0, 0.0, + 1.0, -1.0, 0.0, + -1.0, -1.0, 0.0 + ]; + + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); +} +</pre> + +<p>Diese Routine ist, durch die einfache Art der Szene in diesem Beispiel, sehr einfach gehalten. Es geht los mit dem Aufruf der <code>createBuffer()</code> Methode, die einen Puffer erstellt in dem wir die Punkte speichern können. Der Puffer wird, durch Aufrufen der <code>bindBuffer()</code> Methode, mit dem Kontext verbunden.</p> + +<p>Wenn das erledigt ist, erstellen wir einen JavaScript Array, der die Koordinaten für jeden Punkt des Quadrats enthält. Dieser wird dann in einen WebGL FloatArray umgewandelt und durch die <code>bufferData()</code> Methode werden die Punkte für das Objekt festgelegt.</p> + +<h2 id="Die_Szene_zeichnen">Die Szene zeichnen</h2> + +<p>Jetzt sind die Shader aufgebaut und das Objekt ist erstellt. Wir können die Szene rendern lassen. Da wir in dieser Szene nichts animieren, ist unsere <code>drawScene()</code> Funktion sehr einfach. Es werden einige nützliche Routinen verwendet, die wir uns kurz anschauen.</p> + +<pre class="brush: js">function drawScene() { + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + perspectiveMatrix = makePerspective(45, 640.0/480.0, 0.1, 100.0); + + loadIdentity(); + mvTranslate([-0.0, 0.0, -6.0]); + + gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer); + gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0); + setMatrixUniforms(); + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); +} +</pre> + +<p>Als Erstes wird der Kontext auf unsere Hintergrundfarbe gesetzt und die Kameraperspektive festgelegt. Wir definieren ein Blickfeld von 45°, mit einem Höhen-/Breitenverhältnis von 640 zu 480 (die Größe unseres Canvas). Außerdem legen wir fest, dass wir nur Objekte zwischen 0.1 und 100 Einheiten gerendert haben wollen.</p> + +<p>Dann wird die Position des Quadrats, über das Laden der ursprünglichen Position und der Verschiebung um 6 Einheiten von der Kamera weg, ermittelt. Danach, verbinden wir den Puffer des Quadrats mit dem Kontext, konfigurieren es, und zeichnen das Objekt, in dem wir die <code>drawArrays()</code> Methode aufrufen.</p> + +<p>Das Ergebnis <a href="/samples/webgl/sample2/index.html" title="https://developer.mozilla.org/samples/webgl/sample2/index.html">kann hier ausprobiert werden</a>, wenn Sie einen Browser verwenden, der WebGL unterstützt.</p> + +<h2 id="Matrix_Operationen">Matrix Operationen</h2> + +<p>Matrix Operationen sind schon kompliziert genug. Keiner möchte wirklich den ganzen Code selbst schreiben, der benötigt wird um die Berechnungen selber durchzuführen. Glücklicherweise gibt es <a class="external" href="http://sylvester.jcoglan.com/" title="http://sylvester.jcoglan.com/">Sylvester</a>, eine sehr handliche Bibliothek, die bestens mit Vektor und Matrix Operationen in JavaScript umgehen kann.</p> + +<p>Die <code>glUtils.js</code> Datei, die in dieser Demo benutzt wird, wird bei einer ganzen Reihe von WebGL-Demos, die Web zu finden sind, verwendet. Keiner scheint sich völlig sicher zu sein, woher diese Bibliothek ursprünglich herkommt, aber es vereinfacht den Gebrauch von Sylvester noch weiter, in dem Methoden hinzugefügt werden, die auch spezielle Matrizentypen ermöglichen und HTML ausgegeben werden kann, um die Matrizen anzeigen zu lassen.</p> + +<p>Zusätzlich, definiert diese Demo ein paar hilfreiche Routinen, um an diese Bibliothek für spezielle Aufgaben anzukoppeln. Was genau gemacht wird, ist kein Teil dieses Artikels, aber es gibt einige gute Referenzen zu Matrizen, die online verfügbar sind. Siehe unter <a href="/de/WebGL/Hinzufügen_von_2D_Inhalten_in_einen_WebGL-Kontext#Siehe_auch" title="de/WebGL/Hinzufügen_von_2D_Inhalten_in_einen_WebGL-Kontext#Siehe_auch">Siehe auch</a>, um ein paar aufzulisten.</p> + +<pre class="brush: js">function loadIdentity() { + mvMatrix = Matrix.I(4); +} + +function multMatrix(m) { + mvMatrix = mvMatrix.x(m); +} + +function mvTranslate(v) { + multMatrix(Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4()); +} + +function setMatrixUniforms() { + var pUniform = gl.getUniformLocation(shaderProgram, "uPMatrix"); + gl.uniformMatrix4fv(pUniform, false, new Float32Array(perspectiveMatrix.flatten())); + + var mvUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); + gl.uniformMatrix4fv(mvUniform, false, new Float32Array(mvMatrix.flatten())); +} +</pre> + +<h2 id="Siehe_auch">Siehe auch</h2> + +<ul> + <li><a class="external" href="http://mathworld.wolfram.com/Matrix.html" title="http://mathworld.wolfram.com/Matrix.html">Matrizen</a> auf Wolfram MathWorld (Englisch).</li> + <li><a class="external" href="http://de.wikipedia.org/wiki/Matrix_%28Mathematik%29" title="http://de.wikipedia.org/wiki/Matrix_%28Mathematik%29">Matrix</a> auf Wikipedia.</li> +</ul> + +<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Einführung_in_WebGL", "Web/API/WebGL_API/Tutorial/Farben_mittels_Shader_in_einen_WebGL-Kontext_hinzufügen")}}</p> diff --git a/files/de/web/api/webgl_api/tutorial/index.html b/files/de/web/api/webgl_api/tutorial/index.html new file mode 100644 index 0000000000..34db3f57e6 --- /dev/null +++ b/files/de/web/api/webgl_api/tutorial/index.html @@ -0,0 +1,40 @@ +--- +title: WebGL Tutorial +slug: Web/API/WebGL_API/Tutorial +tags: + - Tutorial + - WebGL +translation_of: Web/API/WebGL_API/Tutorial +--- +<div>{{WebGLSidebar}}</div> + +<div class="summary"> +<p><a class="external" href="http://www.khronos.org/webgl/" title="http://www.khronos.org/webgl/">WebGL</a> enables web content to use an API based on <a class="external" href="http://www.khronos.org/opengles/" title="http://www.khronos.org/opengles/">OpenGL ES</a> 2.0 to perform 3D rendering in an HTML {{HTMLElement("canvas")}} in browsers that support it without the use of plug-ins. WebGL programs consist of control code written in JavaScript and special effects code(shader code) that is executed on a computer's Graphics Processing Unit (GPU). WebGL elements can be mixed with other HTML elements and composited with other parts of the page or page background.</p> +</div> + +<p><span class="seoSummary">This tutorial describes how to use the <code><canvas></code> element to draw WebGL graphics, starting with the basics. The examples provided should give you some clear ideas what you can do with WebGL and will provide code snippets that may get you started in building your own content.</span></p> + +<h2 id="Before_you_start">Before you start</h2> + +<p>Using the <code><canvas></code> element is not very difficult, but you do need a basic understanding of <a href="/en-US/docs/Web/HTML" title="HTML">HTML</a> and <a href="/en-US/docs/Web/JavaScript" title="JavaScript">JavaScript</a>. The <code><canvas></code> element and WebGL are not supported in some older browsers, but are supported in recent versions of all major browsers. In order to draw graphics on the canvas we use a JavaScript context object, which creates graphics on the fly.</p> + +<h2 id="In_diesem_Tutorial">In diesem Tutorial</h2> + +<dl> + <dt><a href="/de/Web/API/WebGL_API/Tutorial/Einführung_in_WebGL">Einführung in WebGL</a></dt> + <dd>Wie man einen WebGL-Kontext herstellt.</dd> + <dt><a href="/de/Web/API/WebGL_API/Tutorial/Hinzufügen_von_2D_Inhalten_in_einen_WebGL-Kontext">Hinzufügen von 2D Inhalten in einen WebGL-Kontext</a></dt> + <dd>Wie eine einfache, flache Form mittels WebGL erstellt wird.</dd> + <dt><a href="/de/Web/API/WebGL_API/Tutorial/Farben_mittels_Shader_in_einen_WebGL-Kontext_hinzufügen">Farben mittels Shader in einen WebGL-Kontext hinzufügen</a></dt> + <dd>Zeigt wie Farben mit Shadern auf die Form gebracht werden können.</dd> + <dt><a href="/de/Web/API/WebGL_API/Tutorial/Objekte_mit_WebGL_animieren">Objekte mit WebGL animieren</a></dt> + <dd>Erklärt wie Objekte rotiert und verschiebt werden, um eine einfache Animation zu erstellen.</dd> + <dt><a href="/de/Web/API/WebGL_API/Tutorial/3D-Objekte_mit_WebGL_erstellen">3D-Objekte mit WebGL erstellen</a></dt> + <dd>Erläutert wie dreidimensionale Objekte erstellt und animiert werden (ein Würfel dient als Beispiel).</dd> + <dt><a href="/de/Web/API/WebGL_API/Tutorial/Texturen_in_WebGL_verwenden">Texturen in WebGL verwenden</a></dt> + <dd>Demonstriert wie Texturen auf die Oberfläche eines Objektes gezeichnet werden können.</dd> + <dt><a href="/de/Web/API/WebGL_API/Tutorial/Beleuchtung_in_WebGL">Beleuchtung in WebGL</a></dt> + <dd>Wie Beleuchtungseffekte in unserem WebGL-Kontext simuliert werden.</dd> + <dt><a href="/de/Web/API/WebGL_API/Tutorial/Animierte_Texturen_in_WebGL">Animierte Texturen in WebGL</a></dt> + <dd>Animierte Texturen werden mittels einem Ogg-Video auf der Oberfläche eines rotierenden Würfels realisiert.</dd> +</dl> diff --git a/files/de/web/api/webgl_api/tutorial/objekte_mit_webgl_animieren/index.html b/files/de/web/api/webgl_api/tutorial/objekte_mit_webgl_animieren/index.html new file mode 100644 index 0000000000..a9eafed6db --- /dev/null +++ b/files/de/web/api/webgl_api/tutorial/objekte_mit_webgl_animieren/index.html @@ -0,0 +1,118 @@ +--- +title: Objekte mit WebGL animieren +slug: Web/API/WebGL_API/Tutorial/Objekte_mit_WebGL_animieren +tags: + - Tutorial + - WebGL +translation_of: Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL +--- +<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Farben_mittels_Shader_in_einen_WebGL-Kontext_hinzufügen", "Web/API/WebGL_API/Tutorial/3D-Objekte_mit_WebGL_erstellen") }}</p> + +<p>Unser Code vom vorherigen Beispiel ist bereits so konfiguriert, dass die WebGL-Szene alle 15 Millisekunden neu gezeichnet wird. Bis jetzt wird zu jeder Zeit das gleiche Bild immer neu gezeichnet. Das wollen wir nun ändern, sodass sich unser Quadrat auf der Bildfläche bewegt.</p> + +<p>In diesem Beispiel rotieren und verschieben wir unser Quadrat in alle drei Dimensionen, sodass es schon in einem 3D Raum existieren kann (obwohl wir bisher nur ein 2D-Objekt erstellt haben).</p> + +<h2 id="Das_Quadrat_rotieren_lassen">Das Quadrat rotieren lassen</h2> + +<p>Fangen wir damit an, das Quadrat im Raum zu rotieren. Als erstes brauchen wir dazu eine Variable in welche wir die Rotation des Quadrats verfolgen können:</p> + +<pre class="brush: js">var squareRotation = 0.0; +</pre> + +<p>Jetzt müssen wir die <code>drawScene()</code> Funktion ändern, um die aktuelle Rotation auf das Quadrat anzuwenden, wenn dies gezeichnet werden soll. Nach der Umrechnung der Startposition für das Quadrat, wenden wir eine Rotation wie diese an:</p> + +<pre class="brush: js">mvPushMatrix(); +mvRotate(squareRotation, [1, 0, 1]); +</pre> + +<p>Das speichert die aktuelle Model-View Matrix und rotiert die Matrix mit dem aktuellen Wert von <code>squareRotation</code> um die X und Z Achsen.</p> + +<p>Nach dem Zeichen müssen wir die Originalmatrix wiederherstellen:</p> + +<pre class="brush: js">mvPopMatrix(); +</pre> + +<p>Wir speichern und stellen die Originalmatrix dann wieder her, um zu verhindern, dass die Rotation auf andere Objekte angewendet wird, die wir vielleicht später noch zeichnen wollen.</p> + +<p>Um letztendlich etwas zu animieren, brauchen wir noch ein paar Zeilen Code, welcher den Wert von <code>squareRotation</code> über die Zeit verändert. Dafür erstellen wir eine neue Variable, die die Zeit aufzeichnet, welche wir zuletzt animiert haben (wir nennen diese <code>lastSquareUpdateTime</code>), dann fügen wir den folgenden Code an das Ende der <code>drawScene()</code> Funktion:</p> + +<pre class="brush: js">var currentTime = (new Date).getTime(); +if (lastSquareUpdateTime) { + var delta = currentTime - lastSquareUpdateTime; + squareRotation += (30 * delta) / 1000.0; +} +lastSquareUpdateTime = currentTime; +</pre> + +<p>Dieser Code benutzt den Betrag der Zeit, die vergangen ist, seitdem wir zum letzten Mal den Wert von <code>squareRotation</code> geändert haben, um festzustellen wie weit das Quadrat rotiert werden soll.</p> + +<h2 id="Das_Quadrat_bewegen">Das Quadrat bewegen</h2> + +<p>Wir können das Quadrat auch verschieben indem wir eine unterschiedliche Position berechnen lassen, bevor wir es zeichnen. Dieses Beispiel zeigt wie eine grundlegende Animation gemacht werden kann. Allerdings möchten Sie in einer echten Anwendung wohl eher etwas weniger Irrsinniges machen.</p> + +<p>Verfolgen wir die Abstände zu jeder Achse für unsere Verschiebung in drei neuen Variablen:</p> + +<pre class="brush: js">var squareXOffset = 0.0; +var squareYOffset = 0.0; +var squareZOffset = 0.0; +</pre> + +<p>Und den Betrag, welcher unsere Postion auf jeder Achse verändern soll, in diesen Variablen:</p> + +<pre class="brush: js">var xIncValue = 0.2; +var yIncValue = -0.4; +var zIncValue = 0.3; +</pre> + +<p>Nun können wir einfach diesen Code zum vorherigen Code, der die Rotation aktualisiert, hinzufügen:</p> + +<pre class="brush: js">squareXOffset += xIncValue * ((30 * delta) / 1000.0); +squareYOffset += yIncValue * ((30 * delta) / 1000.0); +squareZOffset += zIncValue * ((30 * delta) / 1000.0); + +if (Math.abs(squareYOffset) > 2.5) { + xIncValue = -xIncValue; + yIncValue = -yIncValue; + zIncValue = -zIncValue; +} +</pre> + +<p>Das bringt unser Quadrat dazu seine Größe zu verändern, sich willkürlich auf der Fläche zu verschieben, sich vom Betrachter weg und zum Betrachter hin zu bewegen und das alles während das Quadrat auch noch rotiert. Das sieht dann schon eher wie ein Bildschirmschoner aus.</p> + +<p>Wenn Ihr Browser WebGL unterstützt, <a href="/samples/webgl/sample4/index.html" title="https://developer.mozilla.org/samples/webgl/sample4/index.html">ist hier das Beispiel in Aktion</a>.</p> + +<h2 id="Weitere_Matrixoperationen">Weitere Matrixoperationen</h2> + +<p>Dieses Beispiel verwendet einige zusätzliche Matrixoperationen, darunter zwei Routinen, die die Matrizen verschieben, wiederherstellen und in einem Stack aufbewahren und eine Routine, die die Matrix um eine gewissen Anzahl von Grad rotiert:</p> + +<pre class="brush: js">var mvMatrixStack = []; + +function mvPushMatrix(m) { + if (m) { + mvMatrixStack.push(m.dup()); + mvMatrix = m.dup(); + } else { + mvMatrixStack.push(mvMatrix.dup()); + } +} + +function mvPopMatrix() { + if (!mvMatrixStack.length) { + throw("Can't pop from an empty matrix stack."); + } + + mvMatrix = mvMatrixStack.pop(); + return mvMatrix; +} + +function mvRotate(angle, v) { + var inRadians = angle * Math.PI / 180.0; + + var m = Matrix.Rotation(inRadians, $V([v[0], v[1], v[2]])).ensure4x4(); + multMatrix(m); +} +</pre> + +<p>Diese Routinen wurden von einem Beispiel ausgeliehen, welches von Vlad Vukićević geschrieben wurde.</p> + +<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Farben_mittels_Shader_in_einen_WebGL-Kontext_hinzufügen", "Web/API/WebGL_API/Tutorial/3D-Objekte_mit_WebGL_erstellen") }}</p> diff --git a/files/de/web/api/webgl_api/tutorial/texturen_in_webgl_verwenden/index.html b/files/de/web/api/webgl_api/tutorial/texturen_in_webgl_verwenden/index.html new file mode 100644 index 0000000000..eb59417694 --- /dev/null +++ b/files/de/web/api/webgl_api/tutorial/texturen_in_webgl_verwenden/index.html @@ -0,0 +1,159 @@ +--- +title: Texturen in WebGL verwenden +slug: Web/API/WebGL_API/Tutorial/Texturen_in_WebGL_verwenden +tags: + - Tutorial + - WebGL +translation_of: Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL +--- +<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/3D-Objekte_mit_WebGL_erstellen", "Web/API/WebGL_API/Tutorial/Beleuchtung_in_WebGL")}}</p> + +<p>Jetzt wo unser Beispielprogramm über einen rotierenden 3D-Würfel verfügt, wollen wir darauf eine Textur legen, statt der bisher verwendeten, einfachen Farben.</p> + +<h2 id="Texturen_laden">Texturen laden</h2> + +<p>Als Erstes müssen wir ein paar Zeilen Code hinzufügen, um die Texturen zu laden. In unserem Fall werden wir eine einzige Textur verwenden, die auf alle sechs Seiten des rotierenden Würfels gelegt wird, aber die gleiche Technik kann verwendet werden, um jede beliebig viele Texturen auf ein Objekt zu legen.</p> + +<p>Der Code, der die Textur lädt, sieht so aus:</p> + +<pre class="brush: js">function initTextures() { + gl.enable(gl.TEXTURE_2D); + cubeTexture = gl.createTexture(); + cubeImage = new Image(); + cubeImage.onload = function() { handleTextureLoaded(cubeImage, cubeTexture); } + cubeImage.src = "cubetexture.png"; +} + +function handleTextureLoaded(image, texture) { + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, 0, image, true); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); + gl.generateMipmap(gl.TEXTURE_2D); + gl.bindTexture(gl.TEXTURE_2D, null); +} +</pre> + +<p>Die Routine <code>initTextures()</code> aktiviert zunächst die Unterstützung von Texturen, dann wird das GL Textur-Objekt <code>cubeTexture</code> durch Aufruf der GL <code>createTexture()</code> Funktion erstellt. Um die Textur von der Bilddatei zu laden, wird dann ein <code>Image</code>-Objekt erstellt und in die Grafikdatei geladen, die wir als unsere Textur verwenden wollen. Die <code>handleTextureLoaded()</code> Callback-Routine wird ausgeführt, wenn das Bild geladen wurde.</p> + +<p>Um schließlich die Textur zu erstellen, legen wir fest, dass die neue Textur die aktuelle Textur ist, mit welcher wir arbeiten wollen und verbinden diese mit <code>gl.TEXTURE_2D</code>. Danach wird das geladene Bild mit <code>texImage2D()</code> die Bilddaten in die Textur schreiben.</p> + +<p>Die nächsten zwei Zeilen legen Filter für die Textur fest, die steuern, wie das Bild gefiltert wird, wenn es skaliert wird. In diesem Fall verwenden wir lineare Filter, wenn das Bild hoch skaliert wird und <a class="external" href="http://de.wikipedia.org/wiki/Mip_Mapping">Mip-Mapping</a> wenn wir herunter skalieren. Dann wird die Mip-Map generiert, indem <code>generateMipMap()</code> aufgerufen wird. Schließlich teilen wir WebGL mit, dass wir mit der Arbeit an der Textur fertig sind, in dem wir <code>null</code> mit <code>gl.TEXTURE_2D</code> verknüpfen.</p> + +<h2 id="Textur_auf_die_Flächen_legen">Textur auf die Flächen legen</h2> + +<p>Nun ist die Textur geladen und bereit eingesetzt zu werden. Bevor wir die Textur aber verwenden können, müssen wir die Texturkoordinaten auf die Vertices der Flächen des Würfels legen. Das ersetzt den vorherigen Code in <code>initBuffers()</code>, der die Farben für jede Fläche festgelegt hat.</p> + +<pre class="brush: js"> cubeVerticesTextureCoordBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesTextureCoordBuffer); + + var textureCoordinates = [ + // vorne + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + // hinten + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + // oben + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + // unten + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + // rechts + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + // links + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0 + ]; + + gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(textureCoordinates), + gl.STATIC_DRAW); +</pre> + +<p>Zuerst erstellt dieser Code einen GL-Buffer in welchen wir die Texturkoordinaten für jede Fläche speichern werden, dann verknüpfen wir diesen Buffer als das Array in welchen wir schreiben werden.</p> + +<p>Das <code>textureCoordinates</code> Array definiert die Texturkoordinaten entsprechend jedem Vertex von jeder Fläche. Beachten Sie, dass die Texturkoordinaten sich im Bereich von 0.0 bis 1.0 befinden. Beim Texturmapping werden die Dimensionen von Texturen immer auf einen Bereich von 0.0 bis 1.0 normiert, egal welche Größe die Textur wirklich hat.</p> + +<p>Sobald wir das Texturmapping-Array erstellt haben, speichern wir das Array in den Buffer, sodass GL die Daten zur Verfügung hat.</p> + +<h2 id="Die_Shader_aktualisieren">Die Shader aktualisieren</h2> + +<p>Das Shader-Programm - und der Code, der die Shader initialisiert - muss aktualisiert werden, damit die Textur anstatt der Farben verwendet wird.</p> + +<p>Werfen wir zunächst einen Blick auf die einfache Änderung, die in <code>initShaders()</code> benötigt wird:</p> + +<pre class="brush: js"> textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); + gl.enableVertexAttribArray(textureCoordAttribute); +</pre> + +<p>Das ersetzt den Code, der die Vertex Farbattribute enthielt, mit dem, der nun die Texturkoordinaten für jeden Vertex enthält.</p> + +<h3 id="Der_Vertex-Shader">Der Vertex-Shader</h3> + +<p>Als Nächstes müssen wir den Vertex-Shader ersetzen, sodass statt der Farbdaten die Texturkoordinaten abgerufen werden.</p> + +<pre class="brush: html"> <script id="shader-vs" type="x-shader/x-vertex"> + attribute vec3 aVertexPosition; + attribute vec2 aTextureCoord; + + uniform mat4 uMVMatrix; + uniform mat4 uPMatrix; + + varying vec2 vTextureCoord; + + void main(void) { + gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); + vTextureCoord = aTextureCoord; + } + </script> +</pre> + +<p>Die wichtigste Änderung ist hier, dass anstatt die Vertex-Farbe abzurufen, die Texturkoordinaten gesetzt werden. Das gibt den Ort der Textur entsprechend zum Vertex an.</p> + +<h3 id="Der_Fragment-Shader">Der Fragment-Shader</h3> + +<p>Der Fragment-Shader muss in ähnlicher Weise geändert werden:</p> + +<pre class="brush: html"> <script id="shader-fs" type="x-shader/x-fragment"> + varying vec2 vTextureCoord; + + uniform sampler2D uSampler; + + void main(void) { + gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); + } + </script> +</pre> + +<p>Anstatt einen Farbwert auf die Fragment-Farbe zu legen, wird die Fragment-Farbe berechnet in dem der <strong>texel</strong> (der Pixel innerhalb der Textur) abgerufen wird, der am Besten auf die Fragement-Position laut dem Sampler passt.</p> + +<h2 id="Zeichnen_des_textuierten_Würfels">Zeichnen des textuierten Würfels</h2> + +<p>Die Änderungen an der <code>drawScene()</code> Funktion sind einfach (mit der Ausnahme, dass ich nun zur besseren Anschaulichkeit die Verschiebungen entfernt habe und der Würfel nur noch rotiert wird).</p> + +<p>Der Code, der die Farben auf die Textur legt ist weg und wurde ersetzt:</p> + +<pre class="brush: js"> gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, cubeTexture); + gl.uniform1i(gl.getUniformLocation(shaderProgram, "uSampler"), 0); +</pre> + +<p>GL ermöglicht 32 Textur-Register; der Erste davon ist <code>gl.TEXTURE0</code>. Wir verknüpfen unsere geladene Textur zu diesem Register, dann wird der Shader-Sampler <code>uSampler</code> gesetzt (im Shader-Program festgelegt), um die Textur zu benutzen.</p> + +<p>Jetzt sollte der rotierende Würfel gut anzuschauen zu sein. Wenn Ihr Browser WebGL unterstützt, können Sie <a href="/samples/webgl/sample6/index.html" title="https://developer.mozilla.org/samples/webgl/sample6/index.html">das Live-Beispiel ausprobieren</a>.</p> + +<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/3D-Objekte_mit_WebGL_erstellen", "Web/API/WebGL_API/Tutorial/Beleuchtung_in_WebGL")}}</p> |