|
|
(32 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) |
Zeile 1: |
Zeile 1: |
− | {{Warnung|Dieser Artikel befindet sich noch im Aufbau!}}
| + | #REDIRECT [[Tutorial WebGL]] |
− | WebGL ist der neue Standard für OpenGL im Browser. Der Standard ermöglicht es hardwarebeschleunigte 3D-Grafik im Browser darzustellen, ohne dabei auf spezielle Plugins angewiesen zu sein. Bisher wird der Standard von den folgenden Browsern unterstützt:
| |
− | * Mozilla Firefox 3.7a1pre ([http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/ Nightly Build], "Minefield")
| |
− | :: WebGL muss über die Einstellung <tt>about:config</tt> -> <tt>webgl.enabled_for_all_sites</tt> aktiviert werden. Unter Windows kann es einige Probleme geben, wenn kein OpenGL verfügbar ist, in dem Fall muss [http://hacks.mozilla.org/2009/09/webgl-for-firefox/ in den Softwaremodus geschaltet] werden.
| |
− | * WebKit ([http://nightly.webkit.org/ Nightly Build])
| |
− | ** Google Chrome 4.0.221.8 (Nightly Build, [http://www.khronos.org/news/permalink/webgl-seen-in-chrome-browser/ siehe hier])
| |
− | * ...bitte ergänzen...
| |
− | | |
− | | |
− | __TOC__
| |
− | | |
− | | |
− | ==WebGL Context==
| |
− | Um WebGL nutzen zu können benötigt man zunächst einmal natürlich ein HTML5 Canvas-Element, welchem wir passenderweise die ID "canvas" geben. Von diesem Canvas erhalten wir zum einen die spätere Viewportgröße und zum anderen einen sogenannten Context. Das Context-Objekt erlaubt uns sämtliche OpenGL ES 2.0 Funktionen aufzurufen.
| |
− | | |
− | <source lang="javascript">
| |
− | // our WebGL rendering context, it might be useful to use a global variable for this
| |
− | var gl = null;
| |
− | | |
− | // grab the canvas object and its dimensions
| |
− | var canvas = document.getElementById("canvas");
| |
− | var viewportWidth = canvas.width;
| |
− | var viewportHeight = canvas.height;
| |
− | | |
− | // request rendering context from the canvas
| |
− | try {
| |
− | // using Mozilla? (e.g. Firefox, ...)
| |
− | if (!gl) { gl = canvas.getContext("moz-webgl"); }
| |
− | } catch (e) { }
| |
− | try {
| |
− | // using Webkit? (e.g. Google Chrome, ...)
| |
− | if (!gl) { gl = canvas.getContext("webkit-3d"); }
| |
− | } catch (e) { }
| |
− | | |
− | if (!gl) {
| |
− | alert("No known OpenGL context detected! Is it enabled?");
| |
− | return;
| |
− | }
| |
− | </source>
| |
− | | |
− | ==Shader==
| |
− | In OpenGL ES 2.0 herrscht Shader-Zwang, eine [[Feste Funktionspipeline|feste Funktionspipeline]] existiert nicht. Das laden von GLSL-Shadern geschieht wie gewohnt. Zuerst werden Vertex- und Fragmentshader geladen und compiliert. Beide Shader werden dann an ein Program-Objekt angehängt und gelinkt.
| |
− | | |
− | <source lang="javascript">
| |
− | function loadShader(shaderType, shaderSource) {
| |
− | var shader = gl.createShader(shaderType);
| |
− | if (!shader) { return null; }
| |
− | gl.shaderSource(shader, shaderSource);
| |
− | gl.compileShader(shader);
| |
− |
| |
− | if (!gl.getShaderi(shader, gl.COMPILE_STATUS)) {
| |
− | alert(gl.getShaderInfoLog(shader));
| |
− | return null;
| |
− | }
| |
− |
| |
− | return shader;
| |
− | }
| |
− | | |
− | var vertexShaderSource = "...Vertexshader als String...";
| |
− | var fragmentShaderSource = "...Fragmentshader als String...";
| |
− | | |
− | var vertexShader = loadShader(gl.VERTEX_SHADER, vertexShaderSource);
| |
− | var fragmentShader = loadShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
| |
− | if (!vertexShader || !fragmentShader) {
| |
− | alert("Shader problem");
| |
− | }
| |
− | | |
− | // create program object
| |
− | var program = gl.createProgram();
| |
− | | |
− | // attach our two shaders to the program
| |
− | gl.attachShader(program, vertexShader);
| |
− | gl.attachShader(program, fragmentShader);
| |
− | | |
− | // setup attributes and uniforms (optional)
| |
− | gl.bindAttribLocation(program, 0, "aPosition");
| |
− | gl.bindAttribLocation(program, 1, "aNormal");
| |
− | gl.bindAttribLocation(program, 2, "aTexCoord");
| |
− | gl.uniform1i(gl.getUniformLocation(program, "uTexture"), 0);
| |
− | | |
− | // linking
| |
− | gl.linkProgram(program);
| |
− | if (!gl.getProgrami(program, gl.LINK_STATUS)) {
| |
− | alert(gl.getProgramInfoLog(program));
| |
− | }
| |
− | </source>
| |
− | | |
− | Im obigen Beispiel wird der Shader-Quellcode fest als String in den JavaScript-Code integriert. Das ist natürlich ziemlich unübersichtlich. Vom Prinzip spielt es keine Rolle wo der String herkommt. Beispielsweise kann man ihn mit einem HTTP-Request in einer Shader-Datei vom Server laden. Es ist aber auch möglich den Shader-Code als spezielles Script-Element in die HTML-Datei einzubinden.
| |
− | | |
− | <source lang="html4strict">
| |
− | <script id="shader-vs" type="x-shader/x-vertex">
| |
− | attribute vec3 aPosition;
| |
− | attribute vec3 aNormal;
| |
− | attribute vec3 aTexCoord;
| |
− | varying vec3 vNormal;
| |
− | varying vec2 vTexCoord;
| |
− | void main() {
| |
− | gl_Position = vec4(aPosition, 1.0);
| |
− | vTexCoord = aTexCoord;
| |
− | vNormal = aNormal;
| |
− | }
| |
− | </script>
| |
− | | |
− | <script id="shader-fs" type="x-shader/x-fragment">
| |
− | varying vec3 vNormal;
| |
− | varying vec2 vTexCoord;
| |
− | uniform sampler2D uTexture;
| |
− | void main() {
| |
− | gl_FragColor = texture2D(uTexture, vTexCoord);
| |
− | }
| |
− | </script>
| |
− | </source>
| |
− | | |
− | Der Browser hat vom Script-Typ <tt>"x-shader/x-vertex"</tt> natürlich noch nie etwas gehört und wird das Element entsprechend einfach ignorieren. Mit einer einfachen JavaScript-Funktion kann man aber trotzdem an den Inhalt gelangen.
| |
− | | |
− | <source lang="javascript">
| |
− | function getShaderSource(id) {
| |
− | var script = document.getElementById(id);
| |
− | if (!script) { return null; }
| |
− |
| |
− | var source = "";
| |
− | var child = script.firstChild;
| |
− | while (child) {
| |
− | if (child.nodeType == 3) {
| |
− | source += child.textContent;
| |
− | }
| |
− | child = child.nextSibling;
| |
− | }
| |
− | return source;
| |
− | }
| |
− | | |
− | var vertexShaderSource = getShaderSource("shader-vs");
| |
− | var fragmentShaderSource = getShaderSource("shader-fs");
| |
− | </source>
| |
− | | |
− | ==VertexBufferObjects==
| |
− | ...demnächst...
| |
− | | |
− | ==Texturen==
| |
− | Das Laden von Texturen ist relativ einfach, da der Browser bereits über die nötige Infrastruktur zum Laden von Bildern in vielen Formaten bereitstellt. Etwas ungewohnt ist der asynchrone Ladevorgang: Ein Bild steht nicht sofort zur Verfügung, da dieses ja möglicherweise zuerst vom Server geladen werden muss. Sobald aber das Bild verfügbar ist wird das <tt>onload</tt>-Event ausgelöst.
| |
− | <source lang="javascript">
| |
− | function loadTexture(filename) {
| |
− | var texture = gl.createTexture();
| |
− | gl.bindTexture(gl.TEXTURE_2D, texture);
| |
− | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
| |
− | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
| |
− | var image = new Image();
| |
− | image.onload = function() {
| |
− | gl.bindTexture(gl.TEXTURE_2D, texture);
| |
− | gl.texImage2D(gl.TEXTURE_2D, 0, image);
| |
− | gl.generateMipmap(gl.TEXTURE_2D);
| |
− | draw(); // texture now available, we can redraw the scene
| |
− | }
| |
− | image.onerror = function() {
| |
− | alert("error while loading image '"+filename+"'.");
| |
− | }
| |
− | image.src = filename;
| |
− | return texture;
| |
− | }
| |
− | </source>
| |
− | | |
− | ==Links==
| |
− | * [http://people.mozilla.com/~vladimir/webgl/spore/sporeview.html Spore Creature Viewer], ein Viewer für [http://www.collada.org/ COLLADA]-Meshes, allerdings nur für aus dem Spiel [http://www.spore.com/ Spore] exportierte Meshes.
| |
− | * [http://code.google.com/p/chromium/source/browse/trunk/samples/webgl Beispiele für Chromium], funktionieren nicht mit Firefox
| |