Hi,
I tried webgl. I have a square with a texture on it. All worked fine until I added some user interaction. If I simply translate the modelview matrix and get some unbeautiful result. When I'm in translation I can see the texture in his current position and in his last position. I get a stripe on my screen. Frames per sec about 60, I use requestAnimFrame().

here is my drawScene function. I modified code from www.learningwebgl.com/blog/?p=507 .
Code :
    function drawScene() {
        gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 
        mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
 
        mat4.identity(mvMatrix);
 
        mat4.translate(mvMatrix, [-centerX, -centerY, -zoom]);
 
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
        gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
 
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
        gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, cubeVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
 
 
        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, neheTexture);
        gl.uniform1i(shaderProgram.samplerUniform, 0);
 
 
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
        setMatrixUniforms();
        gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
    }
 
    function setMatrixUniforms() {
        gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
        gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
    }
user can only modify centerX, centerY, zoom.

so code could be shorter (or?)
Code :
    function drawScene() {
        gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 
        mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
 
        mat4.identity(mvMatrix);
 
        mat4.translate(mvMatrix, [-centerX, -centerY, -zoom]);
        setMatrixUniforms();
 
        gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
    }
but still looks ugly.

Do i miss some magic?
Is there an other way to translate the texture? like glMatrixMode(GL_TEXTURE) , glTranslatef() in normal OpenGL (bindBuffer and copy tex coords dont work as well)




full file:
(move with up/down, left/right, zoom with page up/down, different textures 0-9)
Code :
<html>
 
<head>
<title>flicker</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
 
 
<script type="text/javascript">
//from src="glMatrix-0.9.5.min.js"
glMatrixArrayType=typeof Float32Array!="undefined"?Float32Array:typeof WebGLFloatArray!="undefined"?WebGLFloatArray:Array;
var mat4={};
mat4.create=function(a){var b=new glMatrixArrayType(16);if(a){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]=a[14];b[15]=a[15]}return b};
mat4.frustum=function(a,b,c,d,e,g,f){f||(f=mat4.create());var h=b-a,i=d-c,j=g-e;f[0]=e*2/h;f[1]=0;f[2]=0;f[3]=0;f[4]=0;f[5]=e*2/i;f[6]=0;f[7]=0;f[8]=(b+a)/h;f[9]=(d+c)/i;f[10]=-(g+e)/j;f[11]=-1;f[12]=0;f[13]=0;f[14]=-(g*e*2)/j;f[15]=0;return f};
mat4.perspective=function(a,b,c,d,e){a=c*Math.tan(a*Math.PI/360);b=a*b;return mat4.frustum(-b,b,-a,a,c,d,e)};
mat4.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]=a[14];b[15]=a[15];return b};
mat4.identity=function(a){a[0]=1;a[1]=0;a[2]=0;a[3]=0;a[4]=0;a[5]=1;a[6]=0;a[7]=0;a[8]=0;a[9]=0;a[10]=1;a[11]=0;a[12]=0;a[13]=0;a[14]=0;a[15]=1;return a};
mat4.translate=function(a,b,c){var d=b[0],e=b[1];b=b[2];if(!c||a==c){a[12]=a[0]*d+a[4]*e+a[8]*b+a[12];a[13]=a[1]*d+a[5]*e+a[9]*b+a[13];a[14]=a[2]*d+a[6]*e+a[10]*b+a[14];a[15]=a[3]*d+a[7]*e+a[11]*b+a[15];return a}var g=a[0],f=a[1],h=a[2],i=a[3],j=a[4],k=a[5],l=a[6],o=a[7],m=a[8],n=a[9],p=a[10],r=a[11];c[0]=g;c[1]=f;c[2]=h;c[3]=i;c[4]=j;c[5]=k;c[6]=l;c[7]=o;c[8]=m;c[9]=n;c[10]=p;c[11]=r;c[12]=g*d+j*e+m*b+a[12];c[13]=f*d+k*e+n*b+a[13];c[14]=h*d+l*e+p*b+a[14];c[15]=i*d+o*e+r*b+a[15];return c};
</script>
 
<script type="text/javascript">
//from src src="webgl-utils.js"
 
/**
 
 * Provides requestAnimationFrame in a cross browser way.
 
 */
 
window.requestAnimFrame = (function() {
 
  return window.requestAnimationFrame ||
 
         window.webkitRequestAnimationFrame ||
 
         window.mozRequestAnimationFrame ||
 
         window.oRequestAnimationFrame ||
 
         window.msRequestAnimationFrame ||
 
         function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
 
           window.setTimeout(callback, 1000/60);
 
         };
 
})();
</script>
 
 
 
<script id="shader-fs" type="x-shader/x-fragment">
    precision mediump float;
 
    varying vec2 vTextureCoord;
 
    uniform sampler2D uSampler;
 
    void main(void) {
        gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
    }
</script>
 
<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>
 
 
<script type="text/javascript">
 
    var gl;
 
    function initGL(canvas) {
        try {
            gl = canvas.getContext("experimental-webgl");
			canvas.width = window.innerWidth;
 
			canvas.height = window.innerHeight;
 
            gl.viewportWidth = canvas.width;
 
            gl.viewportHeight = canvas.height;
 
 
        } catch (e) {
        }
        if (!gl) {
            alert("Could not initialise WebGL, sorry :-(");
        }
    }
 
 
    function getShader(gl, id) {
        var shaderScript = document.getElementById(id);
        if (!shaderScript) {
            return null;
        }
 
        var str = "";
        var k = shaderScript.firstChild;
        while (k) {
            if (k.nodeType == 3) {
                str += k.textContent;
            }
            k = k.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, str);
        gl.compileShader(shader);
 
        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            alert(gl.getShaderInfoLog(shader));
            return null;
        }
 
        return shader;
    }
 
 
    var shaderProgram;
 
    function initShaders() {
        var fragmentShader = getShader(gl, "shader-fs");
        var vertexShader = getShader(gl, "shader-vs");
 
        shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertexShader);
        gl.attachShader(shaderProgram, fragmentShader);
        gl.linkProgram(shaderProgram);
 
        if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
            alert("Could not initialise shaders");
        }
 
        gl.useProgram(shaderProgram);
 
        shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
        gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
 
        shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
        gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
 
        shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
        shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
        shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
    }
 
 
    function handleLoadedTexture(texture, data) {
        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, data);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.bindTexture(gl.TEXTURE_2D, null);
    }
 
    var neheTexture;
	textureSize = 512;
	var pixels = new Uint8Array(4*textureSize*textureSize)
	var pixelsWhite = new Uint8Array(4*textureSize*textureSize)
	var pixelsBlack = new Uint8Array(4*textureSize*textureSize)
 
 
    function initTexture() {
 
		for (var i=0;i<4*textureSize*textureSize;i+=4){
				var bORw = (!(((i/4)%2)+Math.floor((i/4/textureSize)%2)))*255
				pixels[i] =   bORw 
				pixels[i+1] = bORw 
				pixels[i+2] = bORw 
				pixels[i+3] = 255
 
		}
 
		//nehhh = gl.createTexture();
 
 
		neheTexture = gl.createTexture();
 
		gl.bindTexture(gl.TEXTURE_2D, neheTexture);	
 
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
 
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
 
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
 
		gl.bindTexture(gl.TEXTURE_2D, null);
 
		for (var i=0;i<4*textureSize*textureSize;i+=4){	
				pixelsWhite[i] =   255 
				pixelsWhite[i+1] = 255 
				pixelsWhite[i+2] = 255 
				pixelsWhite[i+3] = 255
				pixelsBlack[i] =   0 
				pixelsBlack[i+1] = 0 
				pixelsBlack[i+2] = 0 
				pixelsBlack[i+3] = 255
 
 
		}
 
 
 
    }
 
    var mvMatrix = mat4.create();
    var mvMatrixStack = [];
    var pMatrix = mat4.create();
 
    function mvPushMatrix() {
        var copy = mat4.create();
        mat4.set(mvMatrix, copy);
        mvMatrixStack.push(copy);
    }
 
    function mvPopMatrix() {
        if (mvMatrixStack.length == 0) {
            throw "Invalid popMatrix!";
        }
        mvMatrix = mvMatrixStack.pop();
    }
 
 
    function setMatrixUniforms() {
        gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
        gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
    }
 
 
    var cubeVertexPositionBuffer;
    var cubeVertexTextureCoordBuffer;
    var cubeVertexIndexBuffer;
 
    function initBuffers() {
        cubeVertexPositionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
        vertices = [
            // Front face
            -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);
        cubeVertexPositionBuffer.itemSize = 3;
        cubeVertexPositionBuffer.numItems = 24;
 
        cubeVertexTextureCoordBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
        var textureCoords = [
          // Front face
          0.0, 0.0,
          1.0, 0.0,
          1.0, 1.0,
          0.0, 1.0,
 
 
        ];
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
        cubeVertexTextureCoordBuffer.itemSize = 2;
        cubeVertexTextureCoordBuffer.numItems = 8;
 
        cubeVertexIndexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
        var cubeVertexIndices = [
            0, 1, 2,      0, 2, 3,    // Front face
 
        ];
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
        cubeVertexIndexBuffer.itemSize = 1;
        cubeVertexIndexBuffer.numItems = 6;
    }
 
	var zoom = 0.42;
	var dirX = 0;
	var dirY = 0;
	var centerX =0;
	var centerY =0;
 
	var currentlyPressedKeys = {};
 
    function handleKeyDown(event) {
 
        currentlyPressedKeys[event.keyCode] = true;
 
    }
 
 
 
 
 
    function handleKeyUp(event) {
 
        currentlyPressedKeys[event.keyCode] = false;    }
 
 
 
 
 
 
 
    function handleKeys() {
 
 
        if (currentlyPressedKeys[33]) {
 
            // Page Up
 
            zoom *= 0.99;
 
        }
 
        if (currentlyPressedKeys[34]) {
 
            // Page Down
 
            zoom *= 1.0/0.99;
 
        }
 
        if (currentlyPressedKeys[37]) {
 
            // Left cursor key
 
            dirX=-1.0
 
        }else if (currentlyPressedKeys[39]) {
 
            // Right cursor key
 
            dirX=1.0
 
        }else{
 
		    dirX=0.0
 
		}
 
 
 
 
 
        if (currentlyPressedKeys[38]) {
 
            // Up cursor key
 
            dirY=1.0
 
        }else if (currentlyPressedKeys[40]) {
 
            // Down cursor key
 
            dirY=-1.0
 
        }else{
 
		    dirY=0.0
 
		}
 
		if(currentlyPressedKeys[49]) {
			//white in black
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				var bORw = (!(((i/4)%2)+Math.floor((i/4/textureSize)%2)))*255
				pixels[i] =   bORw 
				pixels[i+1] = bORw 
				pixels[i+2] = bORw 
				pixels[i+3] = 255
 
			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	
 
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[50]) {
			//balck & white chess
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				var bORw = (((i/4)%2)^((i/4/textureSize)%2))*255
				pixels[i] =   bORw 
				pixels[i+1] = bORw 
				pixels[i+2] = bORw 
				pixels[i+3] = 255
 
			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	
 
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
 
		if(currentlyPressedKeys[51]) {
			//x lines black or white
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				var bORw = ((i/4)%2)*255
				pixels[i] =   bORw 
				pixels[i+1] = bORw 
				pixels[i+2] = bORw 
				pixels[i+3] = 255
 
			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	
 
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[52]) {
			//y lines black or white
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				var bORw = Math.floor((i/4/textureSize)%2) *255
				pixels[i] =   bORw 
				pixels[i+1] = bORw 
				pixels[i+2] = bORw 
				pixels[i+3] = 255
 
			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	
 
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[53]) {
			//bw diagonal
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				var bORw =     (  (i/8)%4 ^ ((i/8/textureSize)%4)   )*255
				pixels[i] =   bORw 
				pixels[i+1] = bORw 
				pixels[i+2] = bORw 
				pixels[i+3] = 255
 
			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	
 
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
 
		if(currentlyPressedKeys[54]) {
			//grey random 
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				var value = Math.random()*255
				pixels[i] =   value
				pixels[i+1] = value
				pixels[i+2] = value
				pixels[i+3] = 255
 
			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	
 
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[55]) {
			//all random 
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				pixels[i] =   Math.random()*255
				pixels[i+1] = Math.random()*255
				pixels[i+2] = Math.random()*255
				pixels[i+3] = 255
 
			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	
 
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[56]) {
			//random typed math 1
			var value = new Date().getTime()*1e-3
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				pixels[i] =   0
				pixels[i+1] = (value+ i*i/textureSize/4)*255
				pixels[i+2] = 0
				pixels[i+3] = 255
 
			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	
 
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[57]) {
			//random typed math 2
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				pixels[i] =   ( Math.sin(i/textureSize*2*3.14)+1)*127* (( Math.sin(i/textureSize*2*3.14)+Math.tan(i))>1)
				pixels[i+1] = 0
				pixels[i+2] = 0
				pixels[i+3] = 255
 
			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	
 
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[48]) {
			//random typed math 3
			var value = 4*textureSize*textureSize
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				pixels[i] =   0
				pixels[i+1] = 0
				pixels[i+2] = (value%i)
				pixels[i+3] = 255
 
			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	
 
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
 
 
 
	}
 
    function drawScene() {
        gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 
        mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
 
        mat4.identity(mvMatrix);
 
        mat4.translate(mvMatrix, [-centerX, -centerY, -zoom]);
		setMatrixUniforms();
 
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
        gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
 
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
        gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, cubeVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
 
 
        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, neheTexture);
        gl.uniform1i(shaderProgram.samplerUniform, 0);
 
 
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);        
        gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
    }
 
 
    var lastTime = 0;
 
    function animate() {
        var timeNow = new Date().getTime();
        if (lastTime != 0) {
            var elapsed = timeNow - lastTime;
			var speed = zoom*0.42
			centerX += elapsed/1000*dirX*speed
			centerY += elapsed/1000*dirY*speed
 
        }
        lastTime = timeNow;
    }
 
 
    function tick() {
        requestAnimFrame(tick);
		handleKeys();
 
        drawScene();
		animate();
 
 
    }
 
 
    function webGLStart() {
        var canvas = document.getElementById("flicker");
 
        initGL(canvas);
        initShaders();
        initBuffers();
        initTexture();
 
        gl.clearColor(0.0, 0.3, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);
 
        document.onkeydown = handleKeyDown;
 
        document.onkeyup = handleKeyUp;
 
 
 
 
        tick();
    }
 
 
</script>
 
 
</head>
 
 
<body onload="webGLStart();" marginwidth="0" marginheight="0" topmargin="0" leftmargin="0">
    <canvas id="flicker" style="border: none;" width="800" height="600"></canvas>
</body>
 
</html>