Tutorial WebGL Sample
Aus DGL Wiki
Version vom 26. Oktober 2009, 10:05 Uhr von Coolcat (Diskussion | Beiträge)
Dies ist eine Beispiel Anwendung zum WebGL-Tutorial. Zum ausprobieren den Quelltext in eine Datei kopieren und mit einem WebGL-fähigen Browser öffnen. Es wird eine Textur von der URL "http://wiki.delphigl.com/wiki.png" geladen. Sollte die Anwendung nicht funktionieren stelle sicher, dass die Textur erreichbar ist.
Das ganze sollte ungefähr so aussehen:
<html>
<!--
* WebGL-Test
*
* This sample is part of the WebGL Tutorial at http://delphigl.com
*
* Author:
* Coolcat (Martin Weusten)
* see: http://wiki.delphigl.com/index.php/Benutzer:Coolcat
*
* Licence for this file:
* Creative Commons Attribution 3.0 (CC-BY 3.0)
* see: http://creativecommons.org/licenses/by/3.0/
-->
<head>
<script type="text/javascript">
var gl = null; // our WebGL rendering context
var viewportWidth;
var viewportHeight;
var program; // shader program object
var vbo; // vertexbufferobject
var texture; // texture object
function init() {
// request rendering context from the canvas
// =================================================
var canvas = document.getElementById("canvas");
viewportWidth = canvas.width;
viewportHeight = canvas.height;
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;
}
// basic settings
// =================================================
gl.clearColor(0, 0, 0, 1);
gl.enable(gl.DEPTH_TEST);
// setup shaders
// =================================================
var vertexShaderSource = getShaderSource("shader-vs");
var fragmentShaderSource = getShaderSource("shader-fs");
var vertexShader = loadShader(gl.VERTEX_SHADER, vertexShaderSource);
var fragmentShader = loadShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
if (!vertexShader || !fragmentShader) {
alert("Shader problem");
}
// create program object
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));
}
// setup VBO
// =================================================
// define some vertexdata
var vertices = [
// position XYZ, normal XYZ, texcoord UV => 8 floats per vertex
-0.5, 0.5, 0.0, 0.6, 0.0, 0.8, 0.0, 0.0,
0.5, 0.5, 0.0, 0.6, 0.0, 0.8, 1.0, 0.0,
-0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0,
0.5, -0.5, 0.0, 0.0, 0.6, 0.8, 1.0, 1.0,
// add an additional vertex, this is an workaround for this bug:
// https://bugzilla.mozilla.org/show_bug.cgi?id=521667
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
];
// create VBO
vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, new CanvasFloatArray(vertices), gl.STATIC_DRAW);
// create texture
// =================================================
texture = loadTexture("http://wiki.delphigl.com/wiki.png");
}
function getShaderSource(id) {
var script = document.getElementById(id);
if (!script) { return null; }
var source = "";
var child = script.firstChild;
while (child) {
// node is a "textnode" ?
if (child.nodeType == 3) {
source += child.textContent;
}
child = child.nextSibling;
}
return source;
}
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;
}
function loadTexture(filename) {
// preparations
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();
// register event handlers
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+"'.");
}
// request image from server
image.src = filename;
// return texture object (asynchronous loading, texture NOT available yet!)
return texture;
}
function draw() {
gl.viewport(0, 0, viewportWidth, viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
// setup shader
gl.useProgram(program);
// setup interleaved VBO
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.enableVertexAttribArray(0);
gl.enableVertexAttribArray(1);
gl.enableVertexAttribArray(2);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 8, 0); // position
gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 8, 3); // normal
gl.vertexAttribPointer(2, 2, gl.FLOAT, false, 8, 6); // texcoord
// setup texture
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
// draw the buffer
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}
</script>
<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>
</head>
<body onload="init()">
<div style="text-align: center">
<canvas id="canvas" width="512" height="512"></canvas>
</div>
</body>
</html>