Created
December 3, 2013 23:57
-
-
Save 40thieves/7779934 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE HTML> | |
<html lang="en"> | |
<head> | |
<title>Animated WebGL Scene with Key and Mouse Input.</title> | |
<meta charset="utf-8"> | |
<script src="lib/webgl-debug.js"></script> | |
<script type="text/javascript" src="lib/glMatrix.js"></script> | |
<script src="lib/webgl-utils.js"></script> | |
<script id="shader-vs" type="x-shader/x-vertex"> | |
attribute vec3 aVertexPosition; | |
attribute vec2 aTextureCoordinates; | |
uniform mat4 uMVMatrix; | |
uniform mat4 uPMatrix; | |
varying vec2 vTextureCoordinates; | |
void main() { | |
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); | |
vTextureCoordinates = aTextureCoordinates; | |
} | |
</script> | |
<script id="shader-fs" type="x-shader/x-fragment"> | |
precision mediump float; | |
varying vec2 vTextureCoordinates; | |
uniform sampler2D uSampler; | |
void main() { | |
gl_FragColor = texture2D(uSampler, vTextureCoordinates); | |
} | |
</script> | |
<script type="text/javascript"> | |
// globals | |
var gl | |
, pwgl = {} | |
, canvas | |
// variables for translations and rotations | |
, transY = 0, transZ = 0 | |
, xRot = yRot = zRot = xOffs = yOffs = drag = 0 | |
; | |
pwgl.ongoingImageLoads = []; | |
pwgl.listOfPressedKeys = []; // Keep track of pressed down keys in a list | |
function createGLContext(canvas) { | |
var names = ['webgl', 'experimental-webgl'] | |
, context = null | |
; | |
for (var i = 0; i < names.length; i++) { | |
try { | |
context = canvas.getContext(names[i]); | |
} | |
catch(e) {} | |
if (context) { | |
break; | |
} | |
} | |
if (context) { | |
context.viewportWidth = canvas.width; | |
context.viewportHeight = canvas.height; | |
} | |
else { | |
alert('Failed to create WebGL context!'); | |
} | |
return context; | |
} | |
function loadShaderFromDOM(id) { | |
var shaderScript = document.getElementById(id); | |
// If the element with the specified id is not found, exit | |
if ( ! shaderScript) { | |
return null; | |
} | |
// Loop through the children for the found DOM element and | |
// build up the shader source code as a string | |
var shaderSource = "" | |
, currentChild = shaderScript.firstChild | |
; | |
while (currentChild) { | |
if (currentChild.nodeType == 3) { // 3 corresponds to TEXT_NODE | |
shaderSource += currentChild.textContent; | |
} | |
currentChild = currentChild.nextSibling; | |
} | |
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; | |
} | |
gl.shaderSource(shader, shaderSource); | |
gl.compileShader(shader); | |
if ( ! gl.getShaderParameter(shader, gl.COMPILE_STATUS) && ! gl.isContextLost()) { | |
alert(gl.getShaderInfoLog(shader)); | |
return null; | |
} | |
return shader; | |
} | |
function setupShaders() { | |
var vertexShader = loadShaderFromDOM('shader-vs') | |
, fragmentShader = loadShaderFromDOM('shader-fs') | |
, shaderProgram = gl.createProgram(); | |
gl.attachShader(shaderProgram, vertexShader); | |
gl.attachShader(shaderProgram, fragmentShader); | |
gl.linkProgram(shaderProgram); | |
if ( ! gl.getProgramParameter(shaderProgram, gl.LINK_STATUS) && ! gl.isContextLost()) { | |
alert('Failed to link shaders: ' + gl.getProgramInfoLog(shaderProgram)); | |
} | |
gl.useProgram(shaderProgram); | |
pwgl.vertexPositionAttributeLoc = gl.getAttribLocation(shaderProgram, 'aVertexPosition'); | |
pwgl.vertexTextureAttributeLoc = gl.getAttribLocation(shaderProgram, 'aTextureCoordinates'); | |
pwgl.uniformMVMatrixLoc = gl.getUniformLocation(shaderProgram, 'uMVMatrix'); | |
pwgl.uniformProjMatrixLoc = gl.getUniformLocation(shaderProgram, 'uPMatrix'); | |
pwgl.uniformSamplerLoc = gl.getUniformLocation(shaderProgram, 'uSampler'); | |
gl.enableVertexAttribArray(pwgl.vertexPositionAttributeLoc); | |
gl.enableVertexAttribArray(pwgl.vertexTextureAttributeLoc); | |
pwgl.modelViewMatrix = mat4.create(); | |
pwgl.projectionMatrix = mat4.create(); | |
pwgl.modelViewMatrixStack = []; | |
} | |
function pushModelViewMatrix() { | |
var copyToPush = mat4.create(pwgl.modelViewMatrix); | |
pwgl.modelViewMatrixStack.push(copyToPush); | |
} | |
function popModelViewMatrix() { | |
if (pwgl.modelViewMatrixStack.length == 0) { | |
throw 'Error popModelViewMatrix() - Stack was empty'; | |
} | |
pwgl.modelViewMatrix = pwgl.modelViewMatrixStack.pop(); | |
} | |
function setupFloorBuffers() { | |
pwgl.floorVertexPositionBuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.floorVertexPositionBuffer); | |
var floorVertexPosition = [ | |
// Plane in y=0 | |
5.0, 0.0, 5.0, //v0 | |
5.0, 0.0, -5.0, //v1 | |
-5.0, 0.0, -5.0, //v2 | |
-5.0, 0.0, 5.0 //v3 | |
]; | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(floorVertexPosition), gl.STATIC_DRAW); | |
pwgl.FLOOR_VERTEX_POS_BUF_ITEM_SIZE = 3; | |
pwgl.FLOOR_VERTEX_POS_BUF_NUM_ITEMS = 4; | |
pwgl.floorVertexTextureCoordinateBuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.floorVertexTextureCoordinateBuffer); | |
var floorVertexTextureCoordinates = [ | |
2.0, 0.0, | |
2.0, 2.0, | |
0.0, 2.0, | |
0.0, 0.0 | |
]; | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(floorVertexTextureCoordinates), gl.STATIC_DRAW); | |
pwgl.FLOOR_VERTEX_TEX_COORD_BUF_ITEM_SIZE = 2; | |
pwgl.FLOOR_VERTEX_TEX_COORD_BUF_NUM_ITEMS = 4; | |
pwgl.floorVertexIndexBuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, pwgl.floorVertexIndexBuffer); | |
var floorVertexIndices = [0, 1, 2, 3]; | |
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(floorVertexIndices), gl.STATIC_DRAW); | |
pwgl.FLOOR_VERTEX_INDEX_BUF_ITEM_SIZE = 1; | |
pwgl.FLOOR_VERTEX_INDEX_BUF_NUM_ITEMS = 4; | |
} | |
function setupCubeBuffers() { | |
pwgl.cubeVertexPositionBuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.cubeVertexPositionBuffer); | |
var cubeVertexPosition = [ | |
// Front face | |
1.0, 1.0, 1.0, //v0 | |
-1.0, 1.0, 1.0, //v1 | |
-1.0, -1.0, 1.0, //v2 | |
1.0, -1.0, 1.0, //v3 | |
// Back face | |
1.0, 1.0, -1.0, //v4 | |
-1.0, 1.0, -1.0, //v5 | |
-1.0, -1.0, -1.0, //v6 | |
1.0, -1.0, -1.0, //v7 | |
// Left face | |
-1.0, 1.0, 1.0, //v8 | |
-1.0, 1.0, -1.0, //v9 | |
-1.0, -1.0, -1.0, //v10 | |
-1.0, -1.0, 1.0, //v11 | |
// Right face | |
1.0, 1.0, 1.0, //12 | |
1.0, -1.0, 1.0, //13 | |
1.0, -1.0, -1.0, //14 | |
1.0, 1.0, -1.0, //15 | |
// Top face | |
1.0, 1.0, 1.0, //v16 | |
1.0, 1.0, -1.0, //v17 | |
-1.0, 1.0, -1.0, //v18 | |
-1.0, 1.0, 1.0, //v19 | |
// Bottom face | |
1.0, -1.0, 1.0, //v20 | |
1.0, -1.0, -1.0, //v21 | |
-1.0, -1.0, -1.0, //v22 | |
-1.0, -1.0, 1.0, //v23 | |
]; | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cubeVertexPosition), gl.STATIC_DRAW); | |
pwgl.CUBE_VERTEX_POS_BUF_ITEM_SIZE = 3; | |
pwgl.CUBE_VERTEX_POS_BUF_NUM_ITEMS = 24; | |
// Setup buffer with texture coordinates | |
pwgl.cubeVertexTextureCoordinateBuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.cubeVertexTextureCoordinateBuffer); | |
var textureCoordinates = [ | |
//Front face | |
0.0, 0.0, //v0 | |
1.0, 0.0, //v1 | |
1.0, 1.0, //v2 | |
0.0, 1.0, //v3 | |
// Back face | |
0.0, 1.0, //v4 | |
1.0, 1.0, //v5 | |
1.0, 0.0, //v6 | |
0.0, 0.0, //v7 | |
// Left face | |
0.0, 1.0, //v8 | |
1.0, 1.0, //v9 | |
1.0, 0.0, //v10 | |
0.0, 0.0, //v11 | |
// Right face | |
0.0, 1.0, //v12 | |
1.0, 1.0, //v13 | |
1.0, 0.0, //v14 | |
0.0, 0.0, //v15 | |
// Top face | |
0.0, 1.0, //v16 | |
1.0, 1.0, //v17 | |
1.0, 0.0, //v18 | |
0.0, 0.0, //v19 | |
// Bottom face | |
0.0, 1.0, //v20 | |
1.0, 1.0, //v21 | |
1.0, 0.0, //v22 | |
0.0, 0.0, //v23 | |
]; | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates), gl.STATIC_DRAW); | |
pwgl.CUBE_VERTEX_TEX_COORD_BUF_ITEM_SIZE = 2; | |
pwgl.CUBE_VERTEX_TEX_COORD_BUF_NUM_ITEMS = 24; | |
pwgl.cubeVertexIndexBuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, pwgl.cubeVertexIndexBuffer); | |
var cubeVertexIndices = [ | |
0, 1, 2, 0, 2, 3, // Front face | |
4, 6, 5, 4, 7, 6, // Back face | |
8, 9, 10, 8, 10, 11, // Left face | |
12, 13, 14, 12, 14, 15, // Right face | |
16, 17, 18, 16, 18, 19, // Top face | |
20, 22, 21, 20, 23, 22 // Bottom face | |
]; | |
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW); | |
pwgl.CUBE_VERTEX_INDEX_BUF_ITEM_SIZE = 1; | |
pwgl.CUBE_VERTEX_INDEX_BUF_NUM_ITEMS = 36; | |
} | |
function textureFinishedLoading(image, texture) { | |
gl.bindTexture(gl.TEXTURE_2D, texture); | |
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); | |
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); | |
gl.generateMipmap(gl.TEXTURE_2D); | |
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); | |
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); | |
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT); | |
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT); | |
gl.bindTexture(gl.TEXTURE_2D, null); | |
} | |
function loadImageForTexture(url, texture) { | |
var image = new Image(); | |
image.onload = function() { | |
pwgl.ongoingImageLoads.splice(pwgl.ongoingImageLoads.indexOf(image), 1); | |
textureFinishedLoading(image, texture); | |
} | |
pwgl.ongoingImageLoads.push(image); | |
image.src = url; | |
} | |
function setupTextures() { | |
// Texture for the table | |
pwgl.woodTexture = gl.createTexture(); | |
loadImageForTexture('assets/wood_128x128.jpg', pwgl.woodTexture); | |
// Texture for the floor | |
pwgl.groundTexture = gl.createTexture(); | |
loadImageForTexture('assets/wood_floor_256.jpg',pwgl.groundTexture); | |
// Texture for the box on the table | |
pwgl.boxTexture = gl.createTexture(); | |
loadImageForTexture('assets/wicker_256.jpg', pwgl.boxTexture); | |
} | |
function setupBuffers() { | |
setupFloorBuffers(); | |
setupCubeBuffers(); | |
} | |
function uploadModelViewMatrixToShader() { | |
gl.uniformMatrix4fv(pwgl.uniformMVMatrixLoc, false, pwgl.modelViewMatrix); | |
} | |
function uploadProjectionMatrixToShader() { | |
gl.uniformMatrix4fv(pwgl.uniformProjMatrixLoc, false, pwgl.projectionMatrix); | |
} | |
function drawFloor() { | |
// Bind position buffer | |
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.floorVertexPositionBuffer); | |
gl.vertexAttribPointer(pwgl.vertexPositionAttributeLoc, pwgl.FLOOR_VERTEX_POS_BUF_ITEM_SIZE, gl.FLOAT, false, 0, 0); | |
// Bind texture coordinate buffer | |
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.floorVertexTextureCoordinateBuffer); | |
gl.vertexAttribPointer(pwgl.vertexTextureAttributeLoc, pwgl.FLOOR_VERTEX_TEX_COORD_BUF_ITEM_SIZE, gl.FLOAT, false, 0, 0); | |
gl.activeTexture(gl.TEXTURE0); | |
gl.bindTexture(gl.TEXTURE_2D, pwgl.groundTexture); | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, pwgl.floorVertexIndexBuffer); | |
gl.drawElements(gl.TRIANGLE_FAN, pwgl.FLOOR_VERTEX_INDEX_BUF_NUM_ITEMS, gl.UNSIGNED_SHORT, 0); | |
} | |
function drawCube(texture) { | |
// Bind position buffer | |
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.cubeVertexPositionBuffer); | |
gl.vertexAttribPointer(pwgl.vertexPositionAttributeLoc, pwgl.CUBE_VERTEX_POS_BUF_ITEM_SIZE, gl.FLOAT, false, 0, 0); | |
// bind texture coordinate buffer | |
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.cubeVertexTextureCoordinateBuffer); | |
gl.vertexAttribPointer(pwgl.vertexTextureAttributeLoc, pwgl.CUBE_VERTEX_TEX_COORD_BUF_ITEM_SIZE,gl.FLOAT,false, 0, 0); | |
gl.activeTexture(gl.TEXTURE0); | |
gl.bindTexture(gl.TEXTURE_2D, texture); | |
// Bind index buffer and draw cube | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, pwgl.cubeVertexIndexBuffer); | |
gl.drawElements(gl.TRIANGLES, pwgl.CUBE_VERTEX_INDEX_BUF_NUM_ITEMS, gl.UNSIGNED_SHORT, 0); | |
} | |
function drawTable() { | |
// setup transformations for table top | |
pushModelViewMatrix(); | |
mat4.translate(pwgl.modelViewMatrix, [0.0, 1.0, 0.0], pwgl.modelViewMatrix); | |
mat4.scale(pwgl.modelViewMatrix, [2.0, 0.1, 2.0], pwgl.modelViewMatrix); | |
uploadModelViewMatrixToShader(); | |
// Draw the table top with woodTexture | |
drawCube(pwgl.woodTexture); | |
popModelViewMatrix(); | |
// Draw the table legs | |
for (var i =- 1; i <= 1; i += 2) { | |
for (var j = -1; j <= 1; j += 2) { | |
pushModelViewMatrix(); | |
mat4.translate(pwgl.modelViewMatrix, [i * 1.9, -0.1, j * 1.9], pwgl.modelViewMatrix); | |
mat4.scale(pwgl.modelViewMatrix, [0.1, 1.0, 0.1], pwgl.modelViewMatrix); | |
uploadModelViewMatrixToShader(); | |
drawCube(pwgl.woodTexture); | |
popModelViewMatrix(); | |
} | |
} | |
} | |
function init() { | |
// Initialization that is performed during first startup and when the | |
// event webglcontextrestored is received is included in this function. | |
setupShaders(); | |
setupBuffers(); | |
setupTextures(); | |
gl.clearColor(0.0, 0.0, 0.0, 1.0); | |
gl.enable(gl.DEPTH_TEST); | |
// Initialize some varibles for the moving box | |
pwgl.x = 0.0; | |
pwgl.y = 2.7; | |
pwgl.z = 0.0; | |
pwgl.circleRadius = 4.0; | |
pwgl.angle = 0; | |
// Initialize some variables related to the animation | |
pwgl.animationStartTime = undefined; | |
pwgl.nbrOfFramesForFPS = 0; | |
pwgl.previousFrameTimeStamp = Date.now(); | |
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); | |
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
mat4.perspective(60, gl.viewportWidth / gl.viewportHeight, 1, 100.0, pwgl.projectionMatrix); | |
mat4.identity(pwgl.modelViewMatrix); | |
mat4.lookAt([8, 12, 8], [0, 0, 0], [0, 1, 0], pwgl.modelViewMatrix); | |
} | |
function draw() { | |
pwgl.requestId = requestAnimFrame(draw); | |
var currentTime = Date.now(); | |
handlePressedDownKeys(); | |
if (currentTime - pwgl.previousFrameTimeStamp >= 1000) { | |
pwgl.fpsCounter.innerHTML = pwgl.nbrOfFramesForFPS; | |
pwgl.nbrOfFramesForFPS = 0; | |
pwgl.previousFrameTimeStamp = currentTime; | |
} | |
mat4.translate(pwgl.modelViewMatrix, [0.0, transY, transZ], pwgl.modelViewMatrix); | |
mat4.rotateX(pwgl.modelViewMatrix, xRot / 50, pwgl.modelViewMatrix); | |
mat4.rotateY(pwgl.modelViewMatrix, yRot / 50, pwgl.modelViewMatrix); | |
yRot = xRot = zRot = transY = transZ = 0; | |
uploadModelViewMatrixToShader(); | |
uploadProjectionMatrixToShader(); | |
gl.uniform1i(pwgl.uniformSamplerLoc, 0); | |
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
// Draw floor | |
drawFloor(); | |
// Draw table | |
pushModelViewMatrix(); | |
mat4.translate(pwgl.modelViewMatrix, [0.0, 1.1, 0.0], pwgl.modelViewMatrix); | |
uploadModelViewMatrixToShader(); | |
drawTable(); | |
popModelViewMatrix(); | |
// Draw box | |
pushModelViewMatrix(); | |
// if (currentTime === undefined) { | |
// currentTime = Date.now(); | |
// } | |
if (pwgl.animationStartTime === undefined) { | |
pwgl.animationStartTime = currentTime; | |
} | |
if (pwgl.y < 5) { | |
// console.log('before', pwgl.y); | |
// console.log(pwgl.animationStartTime); | |
// console.log(currentTime); | |
pwgl.y = 2.7 + (currentTime - pwgl.animationStartTime) / 3000 * (5.0 - 2.7); | |
// console.log('after', pwgl.y); | |
} | |
else { | |
pwgl.angle = (currentTime - pwgl.animationStartTime) / 2000 * 2 * Math.PI % (2 * Math.PI); | |
pwgl.x = Math.cos(pwgl.angle) * pwgl.circleRadius; | |
pwgl.z = Math.sin(pwgl.angle) * pwgl.circleRadius; | |
} | |
mat4.translate(pwgl.modelViewMatrix, [pwgl.x, pwgl.y, pwgl.z], pwgl.modelViewMatrix); | |
mat4.scale(pwgl.modelViewMatrix, [0.5, 0.5, 0.5], pwgl.modelViewMatrix); | |
uploadModelViewMatrixToShader(); | |
drawCube(pwgl.boxTexture); | |
popModelViewMatrix(); | |
// Update number of drawn frames to be able to count fps | |
pwgl.nbrOfFramesForFPS++; | |
} | |
function handleKeyDown(e) { | |
pwgl.listOfPressedKeys[e.keyCode] = true; | |
} | |
function handleKeyUp(e) { | |
pwgl.listOfPressedKeys[e.keyCode] = false; | |
} | |
function handlePressedDownKeys() { | |
if (pwgl.listOfPressedKeys[38]) { | |
// Arrow up, increase radius of circle | |
pwgl.circleRadius += 0.1; | |
} | |
if (pwgl.listOfPressedKeys[40]) { | |
// Arrow down, decrease radius of circle | |
pwgl.circleRadius -= 0.1; | |
if (pwgl.circleRadius < 0) { | |
pwgl.circleRadius = 0; | |
} | |
} | |
} | |
function mymousedown(e) { | |
drag = 1; | |
xOffs = e.clientX; | |
yOffs = e.clientY; | |
} | |
function mymouseup(e) { | |
drag = 0; | |
} | |
function mymousemove(e) { | |
if (drag == 0) | |
return; | |
if (e.shiftKey) { | |
transZ = (e.clientY - yOffs)/10; | |
//zRot = (xOffs - e.clientX)*.3; | |
} | |
else if (e.altKey) { | |
transY = -(e.clientY - yOffs)/10; | |
} | |
else { | |
yRot = - xOffs + e.clientX; | |
xRot = - yOffs + e.clientY; | |
} | |
xOffs = e.clientX; | |
yOffs = e.clientY; | |
//console.log("xOff= "+xOffs+" yOff="+yOffs); | |
} | |
function wheelHandler(e) { | |
e.preventDefault(); | |
if (e.delta) { | |
if (e.altKey) | |
transY = -e.detail / 10; | |
else | |
transZ = e.detail / 10; | |
} | |
else if (e.wheelDelta) { | |
if (e.altKey) | |
transY = -e.wheelDelta / 120; | |
else | |
transZ = e.wheelDelta / 120; | |
} | |
} | |
function startup() { | |
canvas = document.getElementById('myGLCanvas'); | |
canvas = WebGLDebugUtils.makeLostContextSimulatingCanvas(canvas); | |
canvas.addEventListener('webglcontextlost', handleContextLost, false); | |
canvas.addEventListener('webglcontextrestored', handleContextRestored, false); | |
document.addEventListener('keydown', handleKeyDown, false); | |
document.addEventListener('keyup', handleKeyUp, false); | |
canvas.addEventListener('mousemove', mymousemove, false); | |
canvas.addEventListener('mousedown', mymousedown, false); | |
canvas.addEventListener('mouseup', mymouseup, false); | |
canvas.addEventListener('mousewheel', wheelHandler, false); | |
canvas.addEventListener('DOMMouseScroll', wheelHandler, false); | |
gl = createGLContext(canvas); | |
init(); | |
pwgl.fpsCounter = document.getElementById('fps'); | |
// Draw the complete scene | |
draw(); | |
} | |
function handleContextLost(e) { | |
e.preventDefault(); | |
cancelRequestAnimFrame(pwgl.requestId); | |
// Ignore all ongoing image loads by removing their onload handler | |
for (var i = 0; i < pwgl.ongoingImageLoads.length; i++) { | |
pwgl.ongoingImageLoads[i].onload = undefined; | |
} | |
pwgl.ongoingImageLoads = []; | |
} | |
function handleContextRestored(e) { | |
init(); | |
pwgl.requestId = requestAnimFrame(draw, canvas); | |
} | |
</script> | |
</head> | |
<body onload="startup();"> | |
<canvas id="myGLCanvas" width="500" height="500"></canvas> | |
<div id="fps-counter">FPS: <span id="fps">--</span></div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note: I put my lib scripts in lib dir to clean it up a bit